If you are generating the SIGINT
with Ctrl+C on a Unix system, then the signal is being sent to the entire process group http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html#tag_11_01_02.
你需要使用setpgid http://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html or setsid http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html将子进程放入不同的进程组中,使其不会接收控制终端生成的信号。
[Edit:]
请务必阅读本文的基本原理部分setpgid
仔细翻页。在这里插入所有潜在的竞争条件有点棘手。
保证100%不会SIGINT
将传递给您的子进程,您需要执行以下操作:
#define CHECK(x) if(!(x)) { perror(#x " failed"); abort(); /* or whatever */ }
/* Block SIGINT. */
sigset_t mask, omask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
CHECK(sigprocmask(SIG_BLOCK, &mask, &omask) == 0);
/* Spawn child. */
pid_t child_pid = fork();
CHECK(child_pid >= 0);
if (child_pid == 0) {
/* Child */
CHECK(setpgid(0, 0) == 0);
execl(...);
abort();
}
/* Parent */
if (setpgid(child_pid, child_pid) < 0 && errno != EACCES)
abort(); /* or whatever */
/* Unblock SIGINT */
CHECK(sigprocmask(SIG_SETMASK, &omask, NULL) == 0);
Strictly speaking, every one of these steps is necessary. You have to block the signal in case the user hits Ctrl+C right after the call to fork
. You have to call setpgid
in the child in case the execl
happens before the parent has time to do anything. You have to call setpgid
in the parent in case the parent runs and someone hits Ctrl+C before the child has time to do anything.
上面的序列很笨拙,但它确实处理了 100% 的竞争条件。