为什么 SIGINT 没有在这里被捕获?

发布于 2024-09-09 06:39:30 字数 607 浏览 2 评论 0原文

这是怎么回事?我以为SIGINT会被发送到前台进程组。

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

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

然后立即按 ctrl+d 然后按 ctrl+c 并注意“捕获信号”是从未打印过。

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

如何解决这个问题? (我已经直接使用 fork() 进行了测试,并了解这是有效的......目前这不是一个可接受的解决方案)

更新:请注意,这没有与“睡眠”有关,只是该命令需要花费一些任意长的时间来运行,这比它周围的 perl 的时间要长得多。如此之多以至于按 ctrl+c 会被发送到命令(因为它在前台进程组中?)并且以某种方式设法永远不会被发送到 perl。

Whats going on here? I thought SIGINT would be sent to the foreground process group.

(I think, maybe, that system() is running a shell which is creating a new process group for the child process? Can anyone confirm this?)

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

Then hit ctrl+d then ctrl+c immediately and notice that "caught signal" is never printed.

I feel like this is a simple thing... anyway to work around this? The problem is that when running a bunch of commands via system results in holding ctrl+c until all iterations are completed (because perl never gets the SIGINT) and is rather annoying...

How can this be worked around? (I already tested using fork() directly and understand that this works... this is not an acceptable solution at this time)

UPDATE: please note, this has nothing to do with "sleeping", only the fact that the command takes some arbitrary long amount of time to run which is considerably more than that of the perl around it. So much so that pressing ctrl+c gets sent to the command (as its in the foreground process group?) and somehow manages to never be sent to perl.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最笨的告白 2024-09-16 06:39:30

来自 perldoc 系统

由于SIGINT和SIGQUIT在系统执行过程中被忽略,
如果您希望程序在收到这些信号后终止,您需要根据返回值自行安排。

@args = ("命令", "arg1", "arg2");
系统(@args)== 0
   或者死“系统@args失败:$?”

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

if ($? == -1) {
    print "执行失败:$!\n";
}
elsif ($? & 127) {
    printf "孩子因信号%d而死亡,%s coredump\n",
       ($? & 127), ($? & 128) ? '有' : '没有';
}
别的 {
    printf "子进程退出,值为 %d\n", $? >>> 8;
}

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

from perldoc system:

Since SIGINT and SIGQUIT are ignored during the execution of system,
if you expect your program to terminate on receipt of these signals you will need to arrange to do so yourself based on the return value.

@args = ("command", "arg1", "arg2");
system(@args) == 0
   or die "system @args failed: $?"

If you'd like to manually inspect system's failure, you can check all possible failure
modes by inspecting $? like this:

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;
}

Alternatively, you may inspect the value of ${^CHILD_ERROR_NATIVE} with the W*() calls from the POSIX module

活雷疯 2024-09-16 06:39:30

我不太明白你想要在这里实现什么......但是你是否尝试过简单地比较:

perl -wle'local $SIG{INT} = sub { print "caught signal"; }; sleep 10;'

你能解释一下你想要达到什么效果,以及为什么要调用 shell 吗?是否可以直接调用外部程序而不涉及shell?

I don't quite get what you're trying to achieve here... but have you tried simply comparing to:

perl -wle'local $SIG{INT} = sub { print "caught signal"; }; sleep 10;'

Can you explain what effect you're trying to go for, and why you are invoking the shell? Can you simply call into the external program directly without involving the shell?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文