我有一个使用Qt Framework的简单程序。 它使用QProcess来执行RAR并压缩一些文件。在我的程序中,我正在捕获SIGINT并在代码中执行某些操作:
signal(SIGINT, &unix_handler);
当SIGINT发生时,我检查RAR进程是否完成,如果不是,我将等待它...问题是(我认为)RAR进程也获得了对我的程序而言的SIGINT在压缩所有文件之前退出。
有没有办法运行RAR进程,以便在我的程序收到它时它不会收到SIGINT?
由于
答案 0 :(得分:27)
如果您在Unix系统上使用Ctrl-c生成SIGINT
,则信号将被发送到整个process group。
您需要使用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
。如果父运行,并且有人在孩子有时间做任何事情之前按Ctrl-C,则必须在父母中调用setpgid
。
上面的序列很笨拙,但确实可以处理100%的竞争条件。
答案 1 :(得分:0)