У меня есть родительский процесс, из которого я запускаю 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 висит вечно и никогда не возвращается, несмотря на то, что потомки родителя успешно завершаются после его зов. Я не могу понять, почему.