Проблема синхронного перехвата SIGCHLD с использованием sigwaitinfo на linux - PullRequest
1 голос
/ 21 апреля 2020

У меня есть родительский процесс, из которого я запускаю 10 дочерних процессов, используя fork(2). После того, как все успешно запущено и запущено, я начинаю синхронно ждать их окончания sh, вызывая 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;
}

вывод:

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...

Я понимаю, что это очень плохой и ненадежный подход (некоторые дочерние процессы могут завершить sh до того, как я настрою синхронный обработчик), но на практике я знаю, что каждый из 10 процессов длится достаточно долго, поэтому они завершаются через некоторое время после синхронный обработчик установлен в родительском объекте.


Проблема в том, что первый вызов sigwaitinfo(2) в while l oop висит вечно и никогда не возвращается, несмотря на то, что потомки родителя успешно завершаются после его зов. Я не могу понять, почему.

...