为什么 bash 后台任务会忽略 SIGINT?

Why bash background task ignores SIGINT?

我注意到 sleep 在由以下人员生成时无法被 SIGINT 杀死:

(sleep 1000 &)

不知为什么会这样。
以下所有都被 SIGINT 杀死:

sleep 1000
sleep 1000 &
(sleep 1000)
( ( (sleep 1000) ) )
( ( (sleep 1000)& ) )

所以我认为它必须与非交互式 bash 有关(进入子 shell 需要括号)并且任务必须在后台 运行。

我写了一个简短的 C 程序来测试行为,发现 sa_handler 设置为 SIG_IGN —— 解释现象,但为什么会这样呢?

我还没有找到任何信息它是否是一个预期的功能(尽管考虑到手册的长度我可能只是错过了它)如果是这样,隐藏它的原因是什么。

我为感兴趣的人提供了 C 代码:

#include <stdlib.h>
#include <stdio.h>

#include <signal.h>

int main() {
    struct sigaction oldact;
    if(sigaction(SIGINT, NULL, &oldact) != 0) {
        printf("Error in sigaction\n");
        exit(1);
    }

    if(oldact.sa_flags & SA_SIGINFO) {
        printf("Using sa_sigaction\n");
    } else {
        if(oldact.sa_handler == SIG_DFL) {
            printf("Default action\n");
        } else if(oldact.sa_handler == SIG_IGN) {
            printf("Ignore signal\n");
        } else {
            printf("Other action\n");
        }
    }
    return 0;
}

编辑:

is great and I accepted it. I wanted to add as to why posix says so that, according to signal(7) SIGINT 和 SIGQUIT 都是来自键盘。因此,在与一个进程分离的进程中忽略它们有点有意义(而不是由 bash 控制的作业)。

编辑 2:

查看 以获得真正的解释为什么。

此构造,(sleep 1000 &) 将您的 sleep 命令放入孙子子 shell 中,没有作业控制:

your-shell
      \
      a compound-list in a subshell
          \
         an asynchronous list in a subshell

先subshell,(compound-list)(agrouping command construct), simply runs the backgrounded command & (an asynchronous list)然后退出。异步列表是 运行 在它自己的 subshell.

最后的子 shell 与您最初的 shell 相去甚远,作业控制没有意义。

根据 POSIX、"[i]f job control is disabled ... when the shell executes an asynchronous list, the commands in the list shall inherit from the shell a signal action of ignored (SIG_IGN) for the SIGINT and SIGQUIT signals."

因此您的睡眠是运行并且SIGINT设置为忽略。