Linux 处理多个 SIGCHLD
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8398298/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Handling multiple SIGCHLD
提问by Manohar
In a system running Linux 2.6.35+ my program creates many child processes and monitors them. If a child process dies I do some clean-up and spawn the process again. I use signalfd()
to get the SIGCHLD
signal in my process. signalfd
is used asynchronously using libevent
.
在运行 Linux 2.6.35+ 的系统中,我的程序创建了许多子进程并监视它们。如果子进程死亡,我会进行一些清理并再次生成该进程。我用来在我的过程中signalfd()
获取SIGCHLD
信号。signalfd
使用异步使用libevent
。
When using signal handlers for non-real time signals, while the signal handler is running for a particular signal further occurrence of the same signal has to be blocked to avoid getting into recursive handlers. If multiple signals arrive at that time then kernel invokes the handler only once (when the signal is unblocked).
当对非实时信号使用信号处理程序时,当信号处理程序正在为特定信号运行时,必须阻止相同信号的进一步发生以避免进入递归处理程序。如果此时有多个信号到达,则内核仅调用一次处理程序(当信号未阻塞时)。
Is it the same behavior when using signalfd()
as well? Since signalfd
based handling doesn't have the typical problems associated with the asynchronous execution of the normal signal handlers I was thinking kernel can queueall the further occurrences of SIGCHLD
?
使用时是否也有相同的行为signalfd()
?由于signalfd
基于处理没有与正常的信号处理我想内核可以异步执行相关的典型问题,排队的所有的再次发生SIGCHLD
?
Can anyone clarify the Linux behavior in this case ...
任何人都可以澄清这种情况下的Linux行为......
采纳答案by Ambroz Bizjak
On Linux, multiple children terminating before you read a SIGCHLD
with signalfd()
will be compressed into a single SIGCHLD
. This means that when you read the SIGCHLD
signal, you have to clean up after allchildren that have terminated:
在 Linux 上,在阅读SIGCHLD
with之前终止的多个子级signalfd()
将被压缩为单个SIGCHLD
. 这意味着当您读取SIGCHLD
信号时,您必须在所有已终止的孩子之后进行清理:
// Do this after you've read() a SIGCHLD from the signalfd file descriptor:
while (1) {
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
if (pid <= 0) {
break;
}
// something happened with child 'pid', do something about it...
// Details are in 'status', see waitpid() manpage
}
I should note that I have in fact seen this signal compression when two child processed terminated at the same time. If I did only a single waitpid()
, one of the children that terminated was not handled; and the above loop fixed it.
我应该注意到,当两个子进程同时终止时,我实际上已经看到了这种信号压缩。如果我只做了一个waitpid()
,终止的孩子之一没有被处理;上面的循环修复了它。
Corresponding documentation:
对应文档:
- http://man7.org/linux/man-pages/man7/signal.7.html"By contrast, if multiple instances of a standard signal are delivered while that signal is currently blocked, then only one instance is queued"
- http://man7.org/linux/man-pages/man3/sigwait.3p.html"If prior to the call to sigwait() there are multiple pending instances of a single signal number, it is implementation-defined whether upon successful return there are any remaining pending signals for that signal number."
- http://man7.org/linux/man-pages/man7/signal.7.html “相比之下,如果一个标准信号的多个实例被传递而该信号当前被阻塞,那么只有一个实例被排队”
- http://man7.org/linux/man-pages/man3/sigwait.3p.html "如果在调用 sigwait() 之前有单个信号编号的多个未决实例,则实现定义是否成功返回该信号编号还有任何剩余的未决信号。”
回答by Pavel ?imerda
Actually the hassle-free way would be the waitfd
functionally that would allow you to add a specific pid to poll()/epoll(). Unfortunately, it wasn't accepted to Linux years ago when it was proposed.
实际上,最简单的方法是在waitfd
功能上允许您向 poll()/epoll() 添加特定的 pid。不幸的是,几年前它被提出时并没有被 Linux 接受。