5

My target is to intercommunicate main process and its "fork" children. Communication is done by signal delivery.

My problem appears when first child gets stuck waiting when waiting for SIGUSR1 signal.

I have no real idea why it gets stuck on that point. Evenmore if I sent signals by console, that child process seems not paying attention.

Could anybody help me?


Here comes the code

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

int N = 5;
int _pipe[2];
pid_t children[5];

void main(){
    pid_t parent_pid;
    pid_t pid;
    int i = 0;

    sigset_t set;
    sigfillset(&set);

    parent_pid = getpid();
    fprintf(stderr,"I am main process, here comes my pid %u\n",getpid());

    if (0>pipe(_pipe)) fprintf(stderr,"Error when creating pipe");

    //Start creating child processes
    while (i < N){
            pid = fork();
            if (pid == 0){
                close(_pipe[1]);
            break;
        }
        else{
            fprintf(stderr,"Created child with pid %u\n",pid);
            children[i] = pid;
            write(_pipe[1],&pid,sizeof(pid_t));
        }
        i = i+1;
    }

    i = 0;

    // What main process does
    if (pid>0){
        close(_pipe[0]);
        close(_pipe[1]);

        sigdelset(&set,SIGUSR2);

        sigdelset(&set,SIGTERM);
        sigdelset(&set,SIGKILL);

        // Main process sends signal to each child
        while(i < N){           
            kill(children[i],SIGUSR1);
            fprintf(stderr,"Sent SIGUSR1 to child %u\n",children[i]);
            // .. Now just wait for SIGUSR2 arrival
            sigsuspend(&set);

            i = i+1;
        }
    }
    // What children do
    else{
        // Wait for main process SIGUSR1 delivery
        sigdelset(&set,SIGUSR1);
        sigsuspend(&set);

        fprintf(stderr, "SIGUSR1 arrived child %u from its father",getpid());

        // Once SIGUSR1 has arrived, pipe is read N times
        while((i < N) && (read(_pipe[0],&pid,sizeof(pid_t))>0)){
            children[i] = pid;
            i = i+1;
        }
        close(_pipe[0]);

        // After reading pipe, a reply is sent to parent process
        kill(parent_pid,SIGUSR2);
    }
}
alk
  • 69,737
  • 10
  • 105
  • 255
xsubira
  • 474
  • 1
  • 5
  • 14

1 Answers1

3

The problem most likely has to-do with the fact that the parent is sending the signals to the child processes immediately after it has forked them, and the child processes aren't blocking the signal. Thus by the time you call sigsuspend() in the child process, the signal has already been delivered to the child, and now it just sits there waiting for a signal that's never coming. You can quickly test this theory by placing a call to sleep() in the main process for a second or two before it starts sending signals. Keep in mind that as your code is structured right now, sigsuspend() won't work right without signal handlers for the signals you're waiting on ... so I suggest the following when working with signals like this:

  1. In the parent process, block all the signals that you're planning on using for communication between the parent and child processes. You'll need to call sigprocmask() for this.
  2. Have the parent fork the child processes
  3. In the child processes simply call sigwait() using a signal set containing the blocked signals being used for communication ... you don't need sigsuspend() for what you're doing here.
  4. After the parent process has sent the signals to the children, it too can call sigwait() to wait for the child process replies.

Here is an example of your code that does work: http://ideone.com/TRcqga

Jason
  • 31,834
  • 7
  • 59
  • 78
  • Thanks a lot @jason, but real problem was not having defined RAS methods for signals whose to receive when "sigsuspended". In following days I will recover the final code I did. – xsubira Dec 19 '12 at 00:20