How to wait for the children processes to send sig

2019-06-05 21:10发布

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>

void handler(int signumber)
{
    return;
}

int main()
{
    int i, pid;
    int children_count = 5;
    int arr_childprocesses[5];
    int parent_pid = getpid();

    for(i=0;i<children_count;i++)
    {
        pid = fork();
        if(pid == -1) 
        {
            perror("Err");
            exit(EXIT_FAILURE);
        }

        if(pid == 0) break;

        arr_childprocesses[i] = pid;
    }

    if (pid == 0) // children
    {
        kill(parent_pid,SIGUSR1);
        printf("Child(%d) sig sent. Waiting 5s...\n",getpid());
        sleep(5);
        printf("Child(%d) terminated.\n",getpid());
    }
    else // parent
    {
        signal(SIGUSR1,handler);
        for(i=0;i<children_count;++i)
        {
            waitpid(arr_childprocesses[i],NULL,0);
            printf("Parent: Signal received.\n");
        }
        printf("Parent(%d) signals received. Waiting 3s...\n",getpid());
        sleep(3);
        printf("Parent(%d) terminated.\n",getpid());
    }

    exit(EXIT_SUCCESS); 
}

I want to wait until all the children send me a signal. Then do some work with the children and with the parent too. But the program stops until all the children terminate. How should I do this?

Result:

enter image description here

Update 1: full code plus result included

标签: c signals fork
1条回答
Juvenile、少年°
2楼-- · 2019-06-05 22:00

You are probably facing a race here.

The parent receives the SIGUSR1 before its handler for this signal had been set up. As the default behaviour on receiving a SIGUSR1 is to end, the parent dies.

You want to setup the signal handler inside the parent before forking off the child.

(If from the programs design it is unacceptbale for the child to have SIGUSR1 signal handler set up, just call signal(SIGUSR1, SIG_DFL) as the 1st statement inside the child to deinstall this handler.)

To prove this theory you might like to temporarily add a sleep(1); inside the child just before the call to kill().


As a hint to fulfill your assignment:

Have a look at sigaction() as it provides a much more powerful interface to signalling then the function signal() does. Especially read about the SA_SIGINFO flag as it enables passing a siginfo_t typed variable to your signal handler. This latter variable carries info on who (identified by PID) sent the signal, which is the key to your solution.

查看更多
登录 后发表回答