使用SIGINT默认处理程序时,从system()返回值 [英] Return value from system() when using SIGINT default handler

查看:53
本文介绍了使用SIGINT默认处理程序时,从system()返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当子进程从终端接收到SIGINT时,我正在经历 system()的一些奇怪的返回值.为了说明,从Perl脚本 parent.pl 中,我使用 system()来运行另一个Perl脚本作为子进程,但是我还需要通过外壳来运行该子进程.,所以我使用了 system'sh','-c',... 形式.因此,子代的父代成为了 sh 进程,而子代的父代成为了 sh 进程. sh 进程变为 parent.pl .另外,为了避免 sh 进程接收到 SIGINT 信号,我将其捕获.

I am experiencing some strange return values from system() when a child process receives a SIGINT from the terminal. To explain, from a Perl script parent.pl I used system() to run another Perl script as a child process, but I also needed to run the child through the shell, so I used the system 'sh', '-c', ... form.. So the parent of the child became the sh process and the parent of the sh process became parent.pl. Also, to avoid having the sh process receiving the SIGINT signal, I trapped it.

例如, 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中止每个子进程,则输出为:

If I run parent.pl (from the command line) and press CTRL-C to abort each child process, the output is:

^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.

Now, I would like to know why I get a return value of 130 for case 1, and a return value of 4 for case 2.

此外,很高兴知道在这种情况下"DEFAULT" 信号处理程序的作用.

Also, it would be nice to know exactly what the "DEFAULT" signal handler does in this case.

注意:如果我将 sh 替换为 bash (并捕获 SIGINT 而不是 INT ,则会返回相同的值>在 bash 中).

Note: the same values are returned if I replace sh with bash ( and trap SIGINT instead of INT in bash ).

另请参阅:

推荐答案

此问题与在使用时向父级传播信号非常相似系统,您之前曾问过.

This question is very similar to Propagation of signal to parent when using system that you asked earlier.

来自我的bash文档:

From my bash docs:

当命令在致命信号N上终止时,bash将使用128 + N的值作为退出状态.

When a command terminates on a fatal signal N, bash uses the value of 128+N as the exit status.

SIGINT通常为2,因此128 + 2等于130.

SIGINT is typically 2, so 128 + 2 give you 130.

Perl的 die 通过检查 $!找出其退出代码!/code>或 $?来捕获未捕获的异常(因此,使用 eval 的情况并非如此):

Perl's die figures out its exit code by inspecting $! or $? for an uncaught exception (so, not the case where you use eval):

exit $! if $!;              # errno
exit $? >> 8 if $? >> 8;    # child exit status
exit 255;                   # last resort

请注意,在这种情况下,Perl会以原样的值退出,而不会上移8位.

Notice that in this case, Perl exits with the value as is, not shifted up 8 bits.

errno值恰好为4(请参见 errno.h ). $!变量是具有不同字符串和数字值的对偶变量.以数字方式使用它(如加零)以获取数字面:

The errno value happens to be 4 (see errno.h). The $! variable is a dualvar with different string and numeric values. Use it numerically (like adding zero) to get the number side:

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

这篇关于使用SIGINT默认处理程序时,从system()返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆