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

时间:2016-01-25 05:27:38

标签: 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
{
    print "trying to exit...\n";
    exit 0;     # Hangs with above open() call
};
alarm 1;

while (1)
{   
    sleep 5;   # Do stuff ...
}

没有open调用它可行,不幸的是删除它不是一个选项,在这种情况下脚本需要它。

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

$SIG{ALRM} = sub
{
    print "trying to close...\n";
    close(IN);            # Hangs ...
    print "ok\n";
    exit 0;
};

我想从信号处理程序中收获孩子并不太高兴......

有没有人知道这方面的好方法?

2 个答案:

答案 0 :(得分:10)

信号处理程序是一个红色鲱鱼,close将阻止,无论如何:

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

close $foo;     # <--- will block

解决此问题的一种方法是通过open然后kill该子项捕获子流程ID:

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

say "subprocess=$subprocess";

kill 'KILL', $subprocess;

close $foo;     # <--- happy now

答案 1 :(得分:1)

直接使用POSIX::_exit()就像手册页建议似乎可以解决这个特定问题。但这闻起来有A-B问题。您是否确定通过使用比普通管道更复杂的处理子流程的方法来解决您的真正问题,例如IPC::Run