[英]Child process receives parent's SIGINT
我有一个使用 Qt 框架的简单程序。 它使用 QProcess 来执行 RAR 并压缩一些文件。 在我的程序中,我正在捕获SIGINT
并在它发生时在我的代码中执行某些操作:
signal(SIGINT, &unix_handler);
当SIGINT
发生时,我检查 RAR 进程是否完成,如果没有完成,我将等待它......问题是(我认为)RAR 进程也获得了用于我的程序的SIGINT
,它在它之前退出已压缩所有文件。
有没有办法运行 RAR 进程,以便在我的程序收到它时它不会收到SIGINT
?
谢谢
如果您在 Unix 系统上使用Ctrl + C生成SIGINT
,那么信号将被发送到整个进程组。
您需要使用setpgid或setsid将子进程放入不同的进程组,这样它就不会收到控制终端生成的信号。
[编辑:]
请务必仔细阅读setpgid
页面的 RATIONALE 部分。 在这里插入所有潜在的竞争条件有点棘手。
为了保证 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);
严格来说,这些步骤中的每一步都是必要的。 如果用户在调用fork
后立即按下 Ctrl + C,您必须阻止信号。 你必须在子进程中调用setpgid
以防execl
在父进程有时间做任何事情之前发生。 您必须在父级中调用setpgid
以防父级运行并且有人在孩子有时间做任何事情之前按了 Ctrl + C。
上面的序列很笨拙,但它确实处理了 100% 的竞争条件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.