2011-04-27 21 views
0

我在我的Perl脚本中有一个INT信号处理程序。当Perl脚本处于系统调用过程中时,它将不会被执行。为什么?系统子程序和INT信号问题

考虑:

$ perl5.12/bin/perl -E "$(cat <<EOF 

    \$SIG{INT} = sub {say q(trapped INT); exit}; 
    say q(sleeping ...); 
    system q(sleep 10000); # INT at this point is not caught by Perl. 

EOF)" 
sleeping ... 

但是,如果我更换一个睡眠调用系统调用,它按预期工作:

$ perl5.12/bin/perl -E "$(cat <<EOF 

    \$SIG{INT} = sub {say q(trapped INT); exit}; 
    say q(sleeping ...); 
    sleep 10000; # replaces the system call from above 

EOF)" 
sleeping ... 
trapped INT 

Perl的版本是:

$ perl5.12/bin/perl -v 

This is perl 5, version 12, subversion 3 (v5.12.3) built for x86_64-linux-thread-multi 
(with 9 registered patches, see perl -V for more detail) 

Copyright 1987-2010, Larry Wall 

Binary build 1204 [294330] provided by ActiveState http://www.ActiveState.com 
Built Feb 9 2011 14:48:47 
... 

回答

5

您可以通过签入检测system()子进程是否被SIGINT杀死克$?,像这样:

use POSIX qw(SIGINT); 

sub interrupt { 
    say "trapped INT"; 
    exit; 
} 

$SIG{INT} = \&interrupt; 

say "sleeping"; 
system ("sleep 100"); 

if (($? & 127) == SIGINT) { 
     interrupt(); 
} elsif ($?) { 
     say "subprocess failed, status $?"; 
} 

INTQUIT信号由perl的外部命令运行时忽略,请参阅system()

1

当调用system()时,正在执行的任何操作都控制着终端。通过键盘控制向它发送任何信号将被发送到正在执行的进程(在这种情况下是系统的睡眠命令)。

捕获信号并在Perl脚本中执行某些操作仅在脚本运行时才起作用。为了有一个陷阱在bash,那么你可以使用trap "command" signal

$ perl -e'system("trap \"echo Trapped\" SIGINT; sleep 10");' 
^CTrapped 
+0

如果这是真的,下面将不会响应^ C警告:'使用IPC :: Open3; $ SIG {INT} = sub {warn(“INT”)}; open3('<&STDIN', '>&STDOUT','>&STDERR', q {perl -e'$ SIG {INT} =“IGNORE”; sleep 5'}); waitpid(-1,0)&& $!{EINTR}; ' – ikegami 2011-04-27 17:53:35

+1

正如Andy所说,处理程序未被调用的原因在于'system'在其运行时将'SIGINT'和'SIGQUIT'设置为'IGNORE'。 – ikegami 2011-04-27 17:54:43