如果您在Unix系统上使用Ctrl-c生成SIGINT
,则信号将发送到整个process group。
您需要使用setpgid或setsid将子进程放入不同的进程组,以便它不会接收控制终端生成的信号。
[编辑]
请务必仔细阅读setpgid
页面的基本原理部分。在这里插入所有潜在的竞争条件是有点棘手的。
要保证没有SIGINT
将交付给你的孩子的过程100%,你需要做的是这样的:
#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);
严格地说,这些步骤每一个需要。如果用户在呼叫fork
后立即点击Ctrl-C,则必须阻止该信号。如果execl
发生在父母有时间做任何事之前发生,您必须在子女中拨打setpgid
。如果父级运行,并且有人在子级有时间做任何事情之前点击Ctrl-C,则必须在父级中调用setpgid
。
上面的序列很笨拙,但它确实能够处理100%的竞争条件。
什么操作系统? – Nemo
目前我在Debian 5.0.8上进行测试 – xx77aBs