子进程收到父进程的 SIGINT
- 2024-10-28 08:37:00
- admin 原创
- 61
问题描述:
我有一个简单的程序,它使用 Qt Framework。它使用 QProcess 执行 RAR 并压缩一些文件。在我的程序中,SIGINT
当发生以下情况时,我会在代码中捕获并执行某些操作:
signal(SIGINT, &unix_handler);
当SIGINT
发生这种情况时,我会检查 RAR 进程是否完成,如果没有,我会等待它...问题是(我认为)RAR 进程也得到了SIGINT
为我的程序准备的,并且它在压缩所有文件之前退出。
有没有办法运行 RAR 进程,以便SIGINT
当我的程序收到它时它不会收到?
谢谢
解决方案 1:
SIGINT
如果您在 Unix 系统上使用Ctrl
+生成C
,那么信号将被发送给整个进程组。
您需要使用setpgid或setsid将子进程放入不同的进程组,这样它就不会接收控制终端生成的信号。
[编辑:]
请务必仔细阅读页面的 RATIONALE 部分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);
严格来说,这些步骤中的每一个都是必要的。您必须阻止信号,以防用户在调用 之后立即点击Ctrl
+ 。您必须调用子进程,以防在父进程有时间做任何事情之前发生 。您必须调用父进程,以防父进程运行并且有人在子进程有时间做任何事情之前点击+ 。C
`forksetpgid
execlsetpgid
Ctrl`C
上面的序列很笨拙,但是它确实处理了 100% 的竞争条件。
解决方案 2:
您在处理程序中做什么?只有某些 Qt 函数可以从 unix 信号处理程序中安全调用。文档中的此页面标识了它们是什么。
主要问题是处理程序将在主 Qt 事件线程之外执行。该页面还提出了一种处理此问题的方法。我更喜欢让处理程序将自定义事件“发布”到应用程序并以这种方式处理它。我在这里发布了一个描述如何实现自定义事件的答案。
解决方案 3:
只需让子进程忽略SIGINT:
child_pid = fork();
if (child_pid == 0) {
/* child process */
signal(SIGINT, SIG_IGN);
execl(...);
}
man sigaction
:
在 execve(2) 期间,已处理信号的配置将重置为默认值;而忽略信号的配置则保持不变。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件