2013-02-07 127 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