Родительский процесс не ожидает выхода всех детей, используя signal()

Первоначально программа просит пользователя ввести количество дочерних процессов для создания. После создания потомков родитель спит и ожидает завершения всех своих потомков с помощью функции обработчика сигнала 'handle_child', зарегистрированной в SIGCHLD.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int to_kill;

void handle_child(int sig)
{
    pid_t id = wait(NULL);
    printf("Reaped child with PID = %d\n",id);
    --to_kill;
    if(to_kill == 0){
        printf("~All children have been reaped successfully.. parent will now exit~\n");
        exit(0);
    }
}

int main()
{
    pid_t id, parent_id = getpid();
    int children, i;
    signal(SIGCHLD, handle_child);
    printf("Enter number of child processes to spawn: ");
    scanf("%d",&children);
    to_kill = children;
    for(i = 0; i < children; ++i){
        id = fork();
        if(id == 0){
            printf("New child with pid = %d\n",getpid());
            sleep(2);
            return 0;
        }
        sleep(1);
    }
    sleep(30);
    return 0;
}

Проблема, с которой я сталкиваюсь, состоит в том, что родитель часто выходит, не пожиная всех своих детей. В некоторых случаях программа работает отлично, а в других случаях она внезапно заканчивается. Что именно здесь происходит?

Один из примеров ошибочного вывода:

Enter number of child processes to spawn: 4
New child with pid = 6458
New child with pid = 6459
Reaped child with PID = 6458
New child with pid = 6461
Reaped child with PID = 6459
New child with pid = 6462
Reaped child with PID = 6461
nishad@nishad-Lenovo-B575:~$

1 ответ

Решение

Я думаю, что вызов сна (30) прерывается прерыванием SIGCHLD, поэтому он не будет спать в течение 30 секунд, а вернется сразу после вызова обработчика сигнала.

Чтобы сделать это правильно, вам нужно будет спать в цикле:

tosleep = 30;
while (tosleep > 0) {
    tosleep = sleep(tosleep);
}
Другие вопросы по тегам