子进程接收父进程的 SIGINT [英] Child process receives parent's SIGINT

查看:40
本文介绍了子进程接收父进程的 SIGINT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 Qt 框架的简单程序.它使用 QProcess 来执行 RAR 并压缩一些文件.在我的程序中,我正在捕获 SIGINT 并在它发生时在我的代码中执行某些操作:

I have one simple program that's using Qt Framework. It uses QProcess to execute RAR and compress some files. In my program I am catching SIGINT and doing something in my code when it occurs:

signal(SIGINT, &unix_handler);

SIGINT 发生时,我检查 RAR 进程是否完成,如果没有,我将等待它......问题是(我认为)RAR 进程也得到 SIGINT 用于我的程序,它在压缩所有文件之前退出.

When SIGINT occurs, I check if RAR process is done, and if it isn't I will wait for it ... The problem is that (I think) RAR process also gets SIGINT that was meant for my program and it quits before it has compressed all files.

有没有办法运行 RAR 进程,使其在我的程序接收到 SIGINT 时不会收到它?

Is there a way to run RAR process so that it doesn't receive SIGINT when my program receives it?

谢谢

推荐答案

如果您使用 Ctrl+C 生成 SIGINTUnix 系统,然后信号被发送到整个进程组.

If you are generating the SIGINT with Ctrl+C on a Unix system, then the signal is being sent to the entire process group.

您需要使用 setpgidsetsid 将子进程放入不同的进程组,以便它不会收到信号由控制终端生成.

You need to use setpgid or setsid to put the child process into a different process group so that it will not receive the signals generated by the controlling terminal.

请务必仔细阅读 setpgid 页面的 RATIONALE 部分.在这里插入所有潜在的竞争条件有点棘手.

Be sure to read the RATIONALE section of the setpgid page carefully. It is a little tricky to plug all of the potential race conditions here.

要保证 100% 不会将 SIGINT 传送到您的子进程,您需要执行以下操作:

To guarantee 100% that no SIGINT will be delivered to your child process, you need to do something like this:

#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,以防 parent 运行并且有人在 Ctrl+Cem>孩子有时间做任何事情.

Strictly speaking, every one of these steps is necessary. You have to block the signal in case the user hits Ctrl+C right after the call to fork. You have to call setpgid in the child in case the execl happens before the parent has time to do anything. You have to call setpgid in the parent in case the parent runs and someone hits Ctrl+C before the child has time to do anything.

上面的序列很笨拙,但它确实处理了 100% 的竞争条件.

The sequence above is clumsy, but it does handle 100% of the race conditions.

这篇关于子进程接收父进程的 SIGINT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆