一尘不染

子进程接收父级的SIGINT

linux

我有一个使用Qt
Framework的简单程序。它使用QProcess执行RAR并压缩一些文件。在我的程序中,我正在捕获SIGINT并在发生代码时做一些事情:

signal(SIGINT, &unix_handler);

SIGINT发生时,我检查RAR进程是否完成,如果不是,我将等待它……问题是(我认为)RAR进程也得到SIGINT了我的程序所需要的,并且在压缩之前退出了所有的文件。

有没有一种方法可以运行RAR进程,以便SIGINT在程序接收到它时不接收它?

谢谢


阅读 407

收藏
2020-06-02

共1个答案

一尘不染

如果要在Unix系统上SIGINT使用Ctrl+ 生成with
C,则信号将发送到整个进程组

您需要使用setpgidsetid将子进程放入另一个进程组,以便它不会接收控制终端生成的信号。


[编辑:]

确保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);

严格来说,这些步骤中的每一个都是必要的。您必须封锁讯号,以防使用者在拨打电话后立即按下Ctrl+
。您必须召集孩子,以防万一在父母有时间做任何事情之前发生。您必须打电话给父母,以防 父母 奔跑而有人在_孩子_ 有时间做任何事情之前打+。C``fork``setpgid``execl``setpgid Ctrl`` C

上面的序列很笨拙,但确实可以处理100%的比赛条件。

2020-06-02