【问题标题】:Handling multiple SIGCHLD处理多个 SIGCHLD
【发布时间】:2012-01-13 23:02:08
【问题描述】:

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

当对非实时信号使用信号处理程序时,当信号处理程序正在为特定信号运行时,必须阻止相同信号的进一步出现以避免进入递归处理程序。如果多个信号同时到达,那么内核只调用一次处理程序(当信号被解除阻塞时)。

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

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

【问题讨论】:

    标签: linux linux-kernel signals


    【解决方案1】:

    在 Linux 上,在您读取带有 signalfd()SIGCHLD 之前终止的多个子级将被压缩为单个 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
    }
    

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

    相应文档:

    【讨论】:

    • @Santhosh:还要注意 signalfd() 本身压缩 SIGCHLD 信号,而不是 epoll。这意味着您不仅不会从 epoll 中获得多个事件,而且您只会从 read() 中获得一个 SIGCHLD 信号;其他人的struct signalfd_siginfo 将永远丢失。
    • 谢谢。我将按照您的建议在循环中执行 waitpid()。从 signalfd_siginfo 我正在访问字段 ssi_code、ssi_status 以获取发送到子进程的信号 # 或 CLD_STOPPED 或 CLI_CONTINUED 等标志。但看起来我更应该使用 WIFEXITED、WIFSIGNALED 之类的宏,它们只需要 waitpid 返回的状态值。
    • @Ambroz, but you will only get a single SIGCHLD signal from the read(); the struct signalfd_siginfo of the others will be lost forever -> 是错误还是设计使然?你能指出一些描述它的文件吗?我认为signalfd 是处理子进程的一种轻松便捷的方式......
    • 谢谢。也许应该到处记录(signalfd、kill、sigwaitinfo、signal(7))?
    • @Vi.: 请参阅man7.org/linux/man-pages/man7/signal.7.html: "相比之下,如果一个标准信号的多个实例在该信号当前被阻塞时被传递,那么只有一个实例在排队"
    【解决方案2】:

    实际上,无忧无虑的方法是waitfd 在功能上允许您将特定的 pid 添加到 poll()/epoll()。不幸的是,它在几年前提出时并未被 Linux 接受。

    【讨论】:

    • 我真的想将其添加为评论而不是答案,对不起。
    • 该功能在 Linux 5.2 中通过 CLONE_PIDFD 标志到 clone 实现,并在 Linux 5.3 中通过 pidfd_open 系统调用进行了扩展。两者都返回一个新的文件描述符,可以使用selectpollepoll_wait 选择可读性,并等待waitidP_PIDFD 检索退出状态。这样做的好处是您可以安全地收获所有孩子,而无需使用任何信号。
    猜你喜欢
    • 2013-07-07
    • 2016-10-31
    • 2020-08-02
    • 2011-11-02
    • 2014-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多