为什么没有SIGINT被抓到这里?

dla*_*tte 7 linux perl signals process

这里发生了什么?我以为SIGINT会被发送到前台进程组.

(我想,也许,system()正在运行一个shell,它正在为子进程创建一个新的进程组?任何人都可以确认这个吗?)

% perl
local $SIG{INT} = sub { print "caught signal\n"; };
system('sleep', '10');
Run Code Online (Sandbox Code Playgroud)

然后立即按ctrl + d然后按ctrl + c,注意"抓住信号"永远不会打印出来.

我觉得这是一件简单的事情......无论如何要解决这个问题?问题是当通过系统运行一堆命令导致持有ctrl + c直到所有迭代完成(因为perl永远不会获得SIGINT)并且相当烦人...

怎么能解决这个问题?(我已经使用fork()直接测试并了解这是有效的......此时这不是一个可接受的解决方案)

更新:请注意,这与"休眠" 无关,只是命令需要花费一些任意长的时间才能运行,这远远超过了它周围的perl.那么按ctrl + c会被发送到命令(就像它在前台进程组中那样?)并以某种方式设法永远不会被发送到perl.

Has*_*kun 4

来自perldoc 系统

由于 SIGINT 和 SIGQUIT 在系统执行期间被忽略,因此如果您希望程序在收到这些信号时终止,您将需要根据返回值自行安排这样做。

@args = ("command", "arg1", "arg2");
system(@args) == 0
   or die "system @args failed: $?"
Run Code Online (Sandbox Code Playgroud)

如果您想手动检查系统故障,可以通过检查 $? 来检查所有可能的故障模式。像这样:

if ($? == -1) {
    print "failed to execute: $!\n";
}
elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
       ($? & 127),  ($? & 128) ? 'with' : 'without';
}
else {
    printf "child exited with value %d\n", $? >> 8;
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用 POSIX 模块的 W*() 调用检查 ${^CHILD_ERROR_NATIVE} 的值

  • 我想我需要重新阅读文档:-/谢谢。 (3认同)