Linux Perl:关闭信号处理程序中的子进程管道挂起?

Linux Perl:关闭信号处理程序中的子进程管道挂起?,linux,perl,pipe,signals,alarm,Linux,Perl,Pipe,Signals,Alarm,我需要在执行阻止io的脚本上超时。 令人惊讶的是,如果有一个通向子流程的开放管道,则exit会挂起: #!/usr/bin/perl (-f "foo") || die "file foo doesn't exist"; open(IN, "tail -f foo |"); $SIG{ALRM} = sub {

我需要在执行阻止io的脚本上超时。
令人惊讶的是,如果有一个通向子流程的开放管道,则
exit
会挂起:

#!/usr/bin/perl                                                                                             
(-f "foo") || die "file foo doesn't exist";
open(IN, "tail -f foo |");

$SIG{ALRM} = sub
{
    print "trying to exit...\n";
    exit 0;     # Hangs with above open() call
};
alarm 1;

while (1)
{   
    sleep 5;   # Do stuff ...
}
如果没有
open
call,则它可以工作,不幸的是,在这种情况下,删除它不是脚本需要的选项

看起来
exit
正在尝试关闭文件句柄,这就是挂起的原因:

$SIG{ALRM} = sub
{
    print "trying to close...\n";
    close(IN);            # Hangs ...
    print "ok\n";
    exit 0;
};
我想把孩子从信号处理器里抓出来是不太开心的


有人知道解决这个问题的好方法吗?

直接使用
POSIX::\u exit()
,就像手册中建议的那样,似乎可以解决这个问题。但这有点A-B问题的味道。您是否确定使用比普通管道更复杂的子流程处理方式(例如
IPC::Run

信号处理程序是一个红鲱鱼,无论:

open my $foo, "tail -f foo |" or die "Can't open process: $!";

close $foo;     # <--- will block
打开我的$foo,“tail-f foo |”或die“无法打开进程:$!”;

关闭$foo;#你当然是对的,傻我!令人困惑的是,提前退出实际上是有效的,但这仅仅是因为它创建了一个竞争条件(孩子还没有准备好)。谢谢
my $subprocess = open my $foo, "tail -f foo |" or die "Can't open process: $!";

say "subprocess=$subprocess";

kill 'KILL', $subprocess;

close $foo;     # <--- happy now