当在 Perl 中使用 CHLD 信号处理程序时,即使使用系统和反引号也会发送 CHLD 信号。但是对于 system 和 backticks 子进程,wait 和 waitpid 似乎都没有设置 $?在 SuSE 11 linux 的信号处理程序中。当 CHLD 信号处理程序处于事件状态时,是否有任何方法来确定反引号命令的返回代码?
我为什么要这个?因为我想 fork (?)并启动一个中等长度的命令,然后调用一个需要很长时间才能产生答案的 perl 包(并且它使用反引号执行外部命令并在 $? 中检查它们的返回码),并且知道什么时候我的命令已完成,因此我可以采取行动,例如启动第二个命令。 (也欢迎提出如何在不使用 SIGCHLD 的情况下完成此操作的建议。)但是由于信号处理程序破坏了反引号 $?值,该包失败。
例子:
use warnings;
use strict;
use POSIX ":sys_wait_h";
sub reaper {
my $signame = shift @_;
while (1) {
my $pid = waitpid(-1, WNOHANG);
last if $pid <= 0;
my $rc = $?;
print "wait()=$pid, rc=$rc\n";
}
}
$SIG{CHLD} = \&reaper;
# system can be made to work by not using $?, instead using system return value
my $rc = system("echo hello 1");
print "hello \$?=$?\n";
print "hello rc=$rc\n";
# But backticks, for when you need the output, cannot be made to work??
my @IO = `echo hello 2`;
print "hello \$?=$?\n";
exit 0;
在我可能尝试访问它的所有地方产生一个 -1 返回码:
hello 1
wait()=-1, rc=-1
hello $?=-1
hello rc=0
wait()=-1, rc=-1
hello $?=-1
所以我找不到任何地方可以访问反引号返回值。
最佳答案
同样的问题已经困扰我好几天了。我相信根据反引号的位置,需要 2 种解决方案。
如果您在子代码中有反引号:
解决方案是将下面的行放在子叉中。我认为您上面的陈述“如果我完全关闭反引号周围的 CHLD 处理程序,那么如果 child 结束,我可能不会收到信号”是不正确的。当 child 退出时,您仍然会在 parent 中获得回调,因为信号仅在 child 内部被禁用。因此,当 child 退出时, parent 仍然会收到信号。只是当 child 的 child (反引号中的部分)退出时, child 没有收到信号。
本地 $SIG{'CHLD'} = 'DEFAULT'
我不是 Perl 专家,我读到过您应该将 CHLD 信号设置为字符串“IGNORE”,但这在我的情况下不起作用。从表面上看,我相信这可能是导致问题的原因。完全保留它似乎也解决了我认为与将其设置为 DEFAULT 相同的问题。
如果父代码中有反引号:
将此行添加到您的收割器函数中:
本地 ($!, $?);
当反引号内的代码完成并且收割者正在设置 $? 时,正在发生的事情是收割者被调用。通过赚取美元?本地它不设置全局 $?。
关于linux - Perl 5.8 : possible to get any return code from backticks when SIGCHLD in use,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26898568/