为什么POSIX要求system(3)忽略SIGINT和SIGQUIT?

时间:2019-05-09 06:24:57

标签: linux shell signals posix

POSIX spec says

  

在等待命令终止时,system()函数将忽略SIGINT和SIGQUIT信号,并阻塞SIGCHLD信号。如果这可能导致应用程序丢失可能杀死该信号的信号,则该应用程序应检查system()的返回值,并在命令由于接收到信号而终止时对应用程序采取适当的操作。 >

这意味着启动长时间运行的子进程的程序将长时间阻塞SIGINTSIGQUIT。这是在我的Ubuntu 18.10笔记本电脑上编译的测试程序:

$ 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

如果我启动在后台运行的测试程序...

$ ./test_system &
[1] 7489

..然后我可以看到SIGINT(2)和SIGQUIT(3)在位掩码中被标记为已忽略。

$ 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无效。

$ kill -SIGINT 7489

..但是将SIGINT发送到进程组确实会杀死它(这是预期的,这意味着进程组中的每个进程都会收到信号-睡眠将退出,系统将返回)。

   $ kill -SIGINT -7489
   [1]+  Done                    ./test_system

问题

  1. 忽略SIGINTSIGQUIT的目的是什么,因为仍然可以通过进程组杀死该进程(在终端中执行^C时会发生这种情况)。
  2. 奖金问题:为什么POSIX要求SIGCHLD被阻止?
  3. 更新如果忽略SIGINTSIGQUIT以确保我们不会把孩子丢在后面,那么为什么SIGTERM没有处理-这就是杀死发送的默认信号!

1 个答案:

答案 0 :(得分:1)

SIGINTSIGQUIT是终端生成的信号。默认情况下,当您分别按下Ctrl+CCtrl+\时,它们将被发送到前台进程组。

我相信在通过system抚养孩子时忽略他们的想法是,终端应该好像它是孩子的​​临时所有者,Ctrl+CCtrl+\应该只是暂时的影响孩子及其后代,而不是父母。

SIGCHLD被阻止,以使system是由子终止引起的SIGCHLD(如果有)将不会触发SIGCHLD处理程序,因为这样的{ {1}}处理程序可能会在SIGCHLD之前收获由system开始的孩子。