Perl:关闭信号处理程序中的子进程管道挂起?
Posted
技术标签:
【中文标题】Perl:关闭信号处理程序中的子进程管道挂起?【英文标题】:Perl: closing subprocess pipe in signal handler hangs? 【发布时间】:2016-01-25 05:27:37 【问题描述】:我需要在执行阻塞 io 的脚本上超时。
令人惊讶的是,如果子进程有一个打开的管道,exit
就会挂起:
#!/usr/bin/perl
(-f "foo") || die "file foo doesn't exist";
open(IN, "tail -f foo |");
$SIGALRM = sub
print "trying to exit...\n";
exit 0; # Hangs with above open() call
;
alarm 1;
while (1)
sleep 5; # Do stuff ...
没有open
调用它可以工作,不幸的是在这种情况下删除它不是一个选项,脚本需要它。
看起来exit
正在尝试关闭文件句柄,这就是挂起的:
$SIGALRM = sub
print "trying to close...\n";
close(IN); # Hangs ...
print "ok\n";
exit 0;
;
我想从信号处理程序中获取孩子不太高兴...
有人知道解决这个问题的好方法吗?
【问题讨论】:
【参考方案1】:信号处理程序是一条红鲱鱼,close 无论如何都会阻塞:
open my $foo, "tail -f foo |" or die "Can't open process: $!";
close $foo; # <--- will block
解决此问题的一种方法是通过open 捕获子进程ID,然后通过kill 捕获该子进程:
my $subprocess = open my $foo, "tail -f foo |" or die "Can't open process: $!";
say "subprocess=$subprocess";
kill 'KILL', $subprocess;
close $foo; # <--- happy now
【讨论】:
当然你说的很对,傻我!令人困惑的部分是早期的exit
确实有效,但这只是因为它创建了一个竞争条件(孩子还没有准备好)。谢谢!【参考方案2】:
像手册页建议的那样直接使用POSIX::_exit()
似乎可以解决这个特定问题。但这有 A-B 问题的味道。您确定使用比普通管道更复杂的处理子流程的方式(例如IPC::Run
)不能更好地解决您的实际问题吗?
【讨论】:
以上是关于Perl:关闭信号处理程序中的子进程管道挂起?的主要内容,如果未能解决你的问题,请参考以下文章