在linux上使用sigwaitinfo同步捕获SIGCHLD时出现问题

在linux上使用sigwaitinfo同步捕获SIGCHLD时出现问题,c,linux,signals,child-process,C,Linux,Signals,Child Process,我有一个父进程,从中我使用fork(2)生成了10个子进程。在所有这些都成功启动并运行之后,我通过在父进程中调用sigwaitinfo(2)开始同步等待它们完成 以下是代码的最低版本: #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <mqueue.h> #include <unistd.h> #include <sys/stat.h> #

我有一个父进程,从中我使用
fork(2)
生成了10个子进程。在所有这些都成功启动并运行之后,我通过在父进程中调用
sigwaitinfo(2)
开始同步等待它们完成

以下是代码的最低版本:

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <mqueue.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <time.h>

int main(void) {

    sigset_t set;
    sigemptyset(&set); // initialize empty set
    sigaddset(&set, SIGCHLD);

    sigset_t old_set;
    sigprocmask(SIG_UNBLOCK, &set, &old_set); // unblock SIGCHLD

    if(sigismember(&old_set, SIGCHLD) == 1) {
        fprintf(stdout, "parent: SIGCHLD was previously blocked");
    }

    for(size_t i = 0; i < 10; i++) {
        pid_t pid = fork();
        if(pid == -1) {
            perror("error forking");
            return EXIT_FAILURE;
        }

        if(pid == 0) {
            sleep(10);
            return EXIT_SUCCESS;
        } else {
            fprintf(stdout, "parent: spawned new child (%d)\n", pid);
        }
    }

    size_t n_children_finished = 0;
    siginfo_t info; // buffer for info about received signal
    while(n_children_finished < 10) {
        fprintf(stdout, "parent: waiting for SIGCHLD...\n");
        int sig = sigwaitinfo(&set, &info);
        // even though it's a set we've only registered SIGCHLD, so no need to check return value
        n_children_finished++;
        fprintf(stdout, "parent: child (PID: %d) finished\n", info.si_pid);
    }

    fprintf(stdout, "parent: all children finished!\n");

    return EXIT_SUCCESS;
}

我知道这是一种非常糟糕和不可靠的方法(一些子进程可能在我设置同步处理程序之前完成),但实际上我知道,10个进程中的每一个进程都持续足够长的时间,以便在同步处理程序在父进程中就位后终止一段时间



问题是while循环中的第一个
sigwaitinfo(2)
调用永远挂起,并且永远不会返回,尽管父级的子级在调用后成功终止。我不明白为什么。

从手册页上的“.”你会这样做吗?我们可以看到一个没有消息队列干扰、有标题和输出的示例吗?我已经将示例更改为MRE,并且还添加了输出。我还添加了一个
sigprocmask(2)
调用,该调用本应取消阻止SIGCHLD(之前似乎没有被阻止,请参见
sigismember(2)
调用),但不幸的是,结果保持不变。我误读了手册页,本应阻止SIGCHLD,而不是取消阻止它。阻止它成功了,谢谢!虽然我还是不明白阻断信号到底能起到什么作用。它是否只是删除了默认的信号配置(对于
SIGCHLD
来说,就是忽略它)?阻止信号会使它不会通过为其配置的任何配置进行处理,从而可以通过
sigwaitinfo
同步接收。明白了。非常感谢。从手册页上,“你会这么做吗?”?我们可以看到一个没有消息队列干扰、有标题和输出的示例吗?我已经将示例更改为MRE,并且还添加了输出。我还添加了一个
sigprocmask(2)
调用,该调用本应取消阻止SIGCHLD(之前似乎没有被阻止,请参见
sigismember(2)
调用),但不幸的是,结果保持不变。我误读了手册页,本应阻止SIGCHLD,而不是取消阻止它。阻止它成功了,谢谢!虽然我还是不明白阻断信号到底能起到什么作用。它是否只是删除了默认的信号配置(对于
SIGCHLD
来说,就是忽略它)?阻止信号会使它不会通过为其配置的任何配置进行处理,从而可以通过
sigwaitinfo
同步接收。明白了。非常感谢。
parent: spawned new child (224386)
parent: spawned new child (224387)
parent: spawned new child (224388)
parent: spawned new child (224389)
parent: spawned new child (224390)
parent: spawned new child (224391)
parent: spawned new child (224392)
parent: spawned new child (224393)
parent: spawned new child (224394)
parent: spawned new child (224395)
parent: waiting for SIGCHLD...