为什么 POSIX 要求 system(3) 忽略 SIGINT 和 SIGQUIT? [英] Why does POSIX demand that system(3) ignores SIGINT and SIGQUIT?
问题描述
system() 函数应忽略 SIGINT 和 SIGQUIT 信号,并在等待命令终止时阻塞 SIGCHLD 信号.如果这可能导致应用程序错过一个会杀死它的信号,那么应用程序应该检查 system() 的返回值,并在命令因接收到信号而终止时采取任何适合应用程序的操作.>
The system() function shall ignore the SIGINT and SIGQUIT signals, and shall block the SIGCHLD signal, while waiting for the command to terminate. If this might cause the application to miss a signal that would have killed it, then the application should examine the return value from system() and take whatever action is appropriate to the application if the command terminated due to receipt of a signal.
这意味着启动一个长时间运行的子进程的程序将被 SIGINT
和 SIGQUIT
阻塞很长时间.这是在我的 Ubuntu 18.10 笔记本电脑上编译的测试程序:
This means that a program that starts a long-running sub-process will have SIGINT
and SIGQUIT
blocked for a long time. Here is a test program compiled on my Ubuntu 18.10 laptop:
$ cat > test_system.c <<< EOF
#include <stdlib.h>
int main() {
system("sleep 86400"); // Sleep for 24 hours
}
EOF
$ gcc test_system.c -o test_system
如果我启动这个在后台运行的测试程序...
If I start this test program running in the background...
$ ./test_system &
[1] 7489
..然后我可以看到 SIGINT
(2) 和 SIGQUIT
(3) 在位掩码中被标记为忽略.
..Then I can see that SIGINT
(2) and SIGQUIT
(3) are marked as ignored in the bitmask.
$ ps -H -o pid,pgrp,cmd,ignored
PID PGRP CMD IGNORED
6956 6956 -bash 0000000000380004
7489 7489 ./test_system 0000000000000006
7491 7489 sh -c sleep 86400 0000000000000000
7492 7489 sleep 86400 0000000000000000
试图用 SIGINT
杀死 test_system 没有效果..
Trying to kill test_system with SIGINT
has no effect..
$ kill -SIGINT 7489
.. 但是将 SIGINT
发送到进程组确实会杀死它(这是意料之中的,这意味着进程组中的每个进程都收到信号 - 睡眠将退出,系统将返回).
.. But sending SIGINT
to the process group does kill it (this is expected, it means that every process in the process group receives the signal - sleep will exit and system will return).
$ kill -SIGINT -7489
[1]+ Done ./test_system
问题
- 忽略
SIGINT
和SIGQUIT
的目的是什么,因为该进程仍然可以通过进程组被杀死(这就是你执行^C
在终端). - 额外问题:为什么 POSIX 要求应该阻止
SIGCHLD
? - 更新 如果
SIGINT
和SIGQUIT
被忽略以确保我们不会留下孩子,那么为什么不处理SIGTERM
- 这是 kill 发送的默认信号!
- What is the purpose of having
SIGINT
andSIGQUIT
ignored since the process can still be killed via the process group (that's what happens when you do a^C
in the terminal). - Bonus question: Why does POSIX demand that
SIGCHLD
should be blocked? - Update If
SIGINT
andSIGQUIT
are ignored to ensure we don't leave children behind, then why is there no handling forSIGTERM
- it's the default signal sent by kill!
推荐答案
SIGINT
和 SIGQUIT
是终端生成的信号.默认情况下,当您分别按 Ctrl+C
或 Ctrl+\
时,它们会发送到前台进程组.
SIGINT
and SIGQUIT
are terminal generated signals. By default, they're sent to the foreground process group when you press Ctrl+C
or Ctrl+\
respectively.
我相信在通过 system
运行孩子时忽略它们的想法是终端应该好像它暂时由孩子和 Ctrl+C
或Ctrl+\
应该暂时只影响孩子及其后代,而不是父母.
I believe the idea for ignoring them while running a child via system
is that the terminal should be as if it was temporarily owned by the child and Ctrl+C
or Ctrl+\
should temporarily only affect the child and its descendants, not the parent.
SIGCHLD
被阻塞,以便 system
的 SIGCHLD
由孩子终止不会触发 SIGCHLD
处理程序(如果您有的话),因为这样的 SIGCHLD
处理程序可能会在 system
收割之前收割由 system
启动的子项.
SIGCHLD
is blocked so that system
's the SIGCHLD
caused by the child terminating won't trigger a SIGCHLD
handler if you have one, because such a SIGCHLD
handler might reap the child started by system
before system
reaps it.
这篇关于为什么 POSIX 要求 system(3) 忽略 SIGINT 和 SIGQUIT?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!