【问题标题】:Perl: how to prevent SIGALRM from closing a pipe?Perl:如何防止 SIGALRM 关闭管道?
【发布时间】:2013-02-07 17:02:49
【问题描述】:

我的管道(文件句柄、套接字)中断(有时)。我可以使用以下代码重现它:

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,我会看到生成的 shell 获得了一个 SIGPIPE。然而,Perl 进程愉快地继续。我该如何解决这个问题?

【问题讨论】:

  • 有什么问题?在您的 ALRM 处理程序中,您调用 exit,因此 perl 退出并关闭文件描述符。当 subshel​​l 写入关闭的文件句柄时,它会得到一个 SIGPIPE。您是否希望 subshel​​l 忽略 SIGPIPE 并永远继续,写入失败?
  • 调用exit ??

标签: perl signals alarm filehandle


【解决方案1】:

问题在于 &lt;FH&gt; 由于系统调用中断而返回 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;
    };
}

【讨论】:

  • 我也不知道“惯用语”,但这是我通常所做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-07
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多