当子进程从终端收到SIGINT时,我遇到来自system()
的一些奇怪的返回值。要解释一下,从Perl脚本parent.pl
我使用system()
运行另一个Perl脚本作为子进程,但我还需要通过shell运行子进程,所以我使用了system 'sh', '-c', ...
form ..因此,孩子的父母成为sh
流程,sh
流程的父成为parent.pl
。另外,为避免sh
进程收到SIGINT
信号,我将其困住了。
例如,parent.pl
:
use feature qw(say);
use strict;
use warnings;
for (1..3) {
my $res = system 'sh', '-c', "trap '' INT; child$_.pl";
say "Parent received return value: " . ($res >> 8);
}
其中child1.pl
:
local $SIG{INT} = "DEFAULT";
sleep 10;
say "Child timed out..";
exit 1;
child2.pl
:
local $SIG{INT} = sub { die };
sleep 10;
say "Child timed out..";
exit 1;
和child3.pl
是:
eval {
local $SIG{INT} = sub { die };
sleep 10;
};
if ( $@ ) {
print $@;
exit 2;
}
say "Child timed out..";
exit 0;
如果我运行parent.pl
(从命令行)并按CTRL-C中止每个子进程,则输出为:
^CParent received return value: 130
^CDied at ./child2.pl line 7.
Parent received return value: 4
^CDied at ./child3.pl line 8.
Parent received return value: 2
现在,我想知道为什么案例1的返回值为130,案例2的返回值为4.
另外,在这种情况下确切知道"DEFAULT"
信号处理程序的作用会很好。
注意:如果我将sh
替换为bash
(并在SIGINT
中隐藏INT
而不是bash
,则会返回相同的值。
另见:
答案 0 :(得分:6)
此问题与您之前提到的Propagation of signal to parent when using system非常相似。
来自我的bash文档:
当命令终止于致命信号N时,bash使用128 + N的值作为退出状态。
SIGINT通常是2,所以128 + 2给你130。
Perl的die通过检查$!
或$?
未捕获的异常来确定其退出代码(因此,不是您使用eval
的情况):
exit $! if $!; # errno
exit $? >> 8 if $? >> 8; # child exit status
exit 255; # last resort
请注意,在这种情况下,Perl以原样退出,而不是向上移位8位。
errno值恰好是4(见errno.h)。 $!
变量是具有不同字符串和数值的dualvar。以数字方式使用它(如加零)得到数字侧:
use v5.10;
local $SIG{INT}=sub{
say "numeric errno is ", $!+0;
die
};
sleep 10;
print q(timed out);
exit 1;
打印:
$ bash -c "perl errno.pl"
^Cnumeric errno is 4
Died at errno.pl line 6.
$ echo $?
4
答案 1 :(得分:1)
不按顺序提问:
此外,很高兴知道" DEFAULT"在这种情况下,信号处理程序。
将给定信号的处理程序设置为"DEFAULT"
,确认或恢复给定信号的默认信号处理程序,其动作取决于信号。详细信息可从the signal(7) manual page获得。 SIGINT
的默认处理程序终止了该过程。
现在,我想知道为什么案例1的返回值为130,案例2的返回值为4.
您的child1显式设置SIGINT
的默认处理程序,因此该信号会导致异常终止。 这样的过程在传统意义上没有退出代码。 shell也会收到SIGINT
,但它会陷阱并忽略它。它为子进程报告的退出状态(因此也为自己报告)反映了杀死孩子的信号(数字2)。
另外两个子进程 catch SIGINT
并正常终止响应。这些确实产生退出代码,shell传递给你(在捕获并忽略SIGINT
之后)。 The documentation for die()
描述了在这种情况下如何确定退出代码,但最重要的是,如果您想要使用特定代码退出,则应使用exit
代替die
。