2013-02-07 126 views
2

我的管道(文件句柄,套接字)中斷(有時)。我可以用下面的代碼重現:Perl:如何防止SIGALRM關閉管道?

my $counter = 5; 
alarm(1); 

open(FH,"while(sleep 2); do date; done |") or die $!; 
while (<FH>) { print; } 
close(FH); 

BEGIN { 
    $SIG{ALRM} = sub { 
     print "alarm!\n"; 
     exit if --$counter == 0; 
     alarm(1); 
    }; 
} 

將產生:

alarm! 
alarm! 
Thu Feb 7 11:46:29 EST 2013 
alarm! 
alarm! 
alarm! 

如果我與strace這個過程中,我看到催生外殼得到一個SIGPIPE。但是,Perl進程繼續愉快。我該如何解決?

+0

什麼問題?在您的ALRM處理程序中,您調用exit,以便perl退出並關閉文件描述符。當子shell寫入關閉的文件句柄時,它會得到一個SIGPIPE。您是否希望subshel​​l忽略SIGPIPE,並且只會一直持續下去,寫入失敗? –

+0

你調用'exit'後,你的Perl進程會繼續快樂嗎? – mob

回答

2

問題是<FH>由於系統調用中斷而返回false。我不知道這是Perl中處理這種慣用方式(並希望看到更好的答案),但以下似乎工作:

my $counter = 5; 
alarm 1; 

open my $fh, '-|', 'while(sleep 2); do date; done' or die $!; 
loop: 
while (<$fh>) { print; } 
goto loop if $!{EINTR}; 
close $fh; 

BEGIN { 
    $SIG{ALRM} = sub { 
     print "alarm!\n"; 
     alarm 1; 
     exit if --$counter <= 0; 
    }; 
} 
+0

我不知道從「慣用」,也沒有,但這是我一般做的。 – darch