处理多个SIGCHLD

Man*_*har 21 linux signals linux-kernel

在运行Linux 2.6.35+的系统中,我的程序会创建许多子进程并监视它们.如果子进程死亡,我会进行一些清理并再次生成进程.我用来在我的过程中signalfd()获取SIGCHLD信号.signalfd使用异步使用libevent.

当将信号处理程序用于非实时信号时,当信号处理程序针对特定信号运行时,必须阻止进一步发生相同的信号以避免进入递归处理程序.如果此时多个信号到达,则内核仅调用一次处理程序(当信号被解除阻塞时).

使用时也是同样的行为signalfd()吗?由于signalfd基本处理没有与正常信号处理程序的异步执行相关的典型问题,我认为内核可以排队所有进一步的事件SIGCHLD

任何人都可以澄清这种情况下的Linux行为......

Amb*_*jak 23

在Linux上,在读取SIGCHLDwith 之前终止的多个子节点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
}
Run Code Online (Sandbox Code Playgroud)

我应该注意到,当两个子进程同时终止时,我实际上看到了这种信号压缩.如果我只做了一个waitpid(),那么终止的一个孩子没有被处理; 并且上面的循环修复了它.

相应文件:

  • @Santhosh:还要注意signalfd()本身压缩SIGCHLD信号,而不是epoll.这意味着您不仅不会从epoll获得多个事件,而且您只能从read()获得单个SIGCHLD信号; 其他人的struct signalfd_siginfo将永远丢失. (3认同)
  • @ Ambroz,`但是您只会从read()中得到一个SIGCHLD信号;其他的struct signalfd_siginfo将会永远丢失`-&gt;是错误还是设计使然?您能指向一些描述它的文件吗?我认为`signalfd`是处理子进程的便捷方式... (2认同)