【问题标题】:Why does POSIX demand that system(3) ignores SIGINT and SIGQUIT?为什么 POSIX 要求 system(3) 忽略 SIGINT 和 SIGQUIT?
【发布时间】:2019-05-09 06:24:56
【问题描述】:

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 - 这是 kill 发送的默认信号!

【问题讨论】:

    标签: linux shell signals posix


    【解决方案1】:

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

    我认为在通过system 运行孩子时忽略它们的想法是终端应该暂时归孩子所有,Ctrl+CCtrl+\ 应该暂时只影响孩子及其后代,而不是父级。

    SIGCHLD 被阻塞,因此system 的子进程终止导致的SIGCHLD 不会触发SIGCHLD 处理程序,因为这样的SIGCHLD 处理程序可能会收割子进程启动由systemsystem 收获它之前。

    【讨论】:

    • 好的,所以这不是关于管理子进程的生命周期,而是关于使终端工作符合用户期望。这听起来很合理。
    猜你喜欢
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多