2011-04-27 19 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