Thread: signal to process

  1. #1
    Registered User
    Join Date
    May 2011
    Posts
    116

    signal to process

    I have a parent process and many children.
    The childrens' pids are stored in an array of ints.
    at some point of the program I want to send a signal to all the children from the parent process and then wait until ALL of them send a signal back to the parent.For one child it works but for more there're problems.

    Code:
    //parent process
    int pids[c]; //c is the number of children
    for(int i=0;i<c;i++){
       kill(pids[i],REQ); //req is the signal the parent sends
    }
    this loop doesn't work for many children as they seem never to catch the signal.When I change it to:

    Code:
    kill(0,REQ); //send signal to every process
    they catch the signal from the parent,and they execute their function f:

    Code:
    void f(int signum){
         cout<<"Signal caught from child!"<<endl;
         kill(getppid(),REQ1); //send a response signal to the parent
         exit(1);
    }
    but the parent never receives that signal,and I assume is due to the fact that after the parent's command "kill" (where the signal is sent to all of its children) there's the return statement of the main function.So I guess the parent never receives any signal from the children because its already terminated.Is there a way for the parrent to wait until it receives c signal responses and then terminate?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    waitpid(2): wait for process to change state - Linux man page
    I can't see the point of sending signals in both directions.

    Try something like
    Code:
    for(int i=0;i<c;i++){
       kill(pids[i],REQ); //req is the signal the parent sends
       int status;
       waitpid(pids[i],&status,0);
       if ( WIFSIGNALED(status) ) {
          int sig = WTERMSIG(status);
          // sig == REQ if that's why it died
       }
    }

    Another issue for N children all sending signals to the parent is that signals are NOT queued. They're not suitable for high bandwidth information.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by Salem View Post
    waitpid(2): wait for process to change state - Linux man page
    I can't see the point of sending signals in both directions.

    Try something like
    Code:
    for(int i=0;i<c;i++){
       kill(pids[i],REQ); //req is the signal the parent sends
       int status;
       waitpid(pids[i],&status,0);
       if ( WIFSIGNALED(status) ) {
          int sig = WTERMSIG(status);
          // sig == REQ if that's why it died
       }
    }

    Another issue for N children all sending signals to the parent is that signals are NOT queued. They're not suitable for high bandwidth information.

    I am supposed to do send signals both directions,is not actually my choice
    The parent when it has finished everything it has to do sends the signal REQ to all children and when they catch it they send a response signal REQ1 and then terminate.
    When the parent receives number of signals equal to the number of processes terminates too.

    in the solution you suggested the children dont seem to catch the signal
    It must be again this command's fault:

    kill(pids[i],REQ);

    edit::For c=1 works fine as it does mine,for more than one processes there's the problem
    Last edited by quo; 06-08-2012 at 03:28 AM.

  4. #4
    Registered User
    Join Date
    May 2011
    Posts
    116
    I just figured that the problem must be here:

    Code:
    waitpid(pids[i],&status,0);
    The parent sends the signal to the first child and receives the answer,executes its function which handles the signal and then blocks on waitpid and never goes to the next loop of for-loop

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Actually, if your signals are being caught and handled, then the process isn't going to die, so there is no need to wait.

    You only need waitpid IF the child is going to die.

    Try this
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <unistd.h>
    
    #define SIG_PARENT_TO_CHILD SIGUSR1
    #define SIG_CHILD_TO_PARENT SIGUSR2
    
    volatile int p1 = 0;
    void parent_catching_child ( int sig ) {
      printf("Parent caught %d\n",sig);
      p1++;
    }
    
    volatile int c1 = 0;
    void child_catching_parent ( int sig ) {
      printf("Child caught %d\n",sig);
      c1++;
    }
    
    void doChild ( void ) {
      signal(SIG_PARENT_TO_CHILD,child_catching_parent);
      sleep(1);
      while ( !c1 ) {
        sleep(1);
      }
      kill(getppid(),SIG_CHILD_TO_PARENT);
    }
    
    void doParent ( pid_t childPid ) {
      signal(SIG_CHILD_TO_PARENT,parent_catching_child);
      sleep(1);
      kill(childPid,SIG_PARENT_TO_CHILD);
      while( !p1 ) {
        sleep(1);
      }
      int status;
      waitpid(childPid,&status,0);
      if ( WIFEXITED(status) ) {
        int ret = WEXITSTATUS(status);
        printf("Child exited normally with %d\n",ret);
      } else
      if ( WIFSIGNALED(status) ) {
        int sig = WTERMSIG(status);
        printf("Child exited abnormally with signal %d\n",sig);
      } else {
        fprintf(stderr,"Oops\n");
      }
    }
    
    int main ( ) {
      pid_t pid;
      if ( (pid=fork()) == 0 ) {
        doChild();
      } else {
        doParent(pid);
      }
      return 0;
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by Salem View Post
    Actually, if your signals are being caught and handled, then the process isn't going to die, so there is no need to wait.

    You only need waitpid IF the child is going to die.
    Thank you very much for your answer.There're just a few things I don't understand,if you could explain to me
    First,what is the use of the volatile int?(Never seen that again before)
    Secondly,what I want is the parent to send the SIGUSR2 to all of its children and when they receive it to send him back SIGUSR1.When the parent receives that signal from all of his children then it terminates.On the other hand when the children receive SIGUSR2 and send back to the parent the SIGUSR1,they also have to terminate.I'm saying all these again because I want to make sure what the code you suggested does.It's very nice but I cannot fully understand what you're doing..

    Also what are the sleeps for?Are they necessary?

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > First,what is the use of the volatile int?(Never seen that again before)
    Consider it an opportunity to learn by reading your C book.

    > Also what are the sleeps for?Are they necessary?
    Well you could remove them and see what happens.

    > Secondly,what I want is the parent to send the SIGUSR2 to all of its children and when they receive it to send him back SIGUSR1.
    Like I said previously, there is no issue with this in theory, except for the fact that signals are NOT QUEUED.
    1 parent sending N signals to N children (one per child) isn't a problem.
    N children sending N signals back to 1 parent is however.

    I'd like to see some of your attempts at solving this before just giving you your homework.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by Salem View Post
    > First,what is the use of the volatile int?(Never seen that again before)
    Consider it an opportunity to learn by reading your C book.

    > Also what are the sleeps for?Are they necessary?
    Well you could remove them and see what happens.

    > Secondly,what I want is the parent to send the SIGUSR2 to all of its children and when they receive it to send him back SIGUSR1.
    Like I said previously, there is no issue with this in theory, except for the fact that signals are NOT QUEUED.
    1 parent sending N signals to N children (one per child) isn't a problem.
    N children sending N signals back to 1 parent is however.

    I'd like to see some of your attempts at solving this before just giving you your homework.

    I tried it as you suggested and a strange thing occured..
    In the child process there's the loop:

    Code:
    while(!c1){
    //do things--I removed sleep()--
    }
    once the child is alive it runs this loop.In the loop there's a getline that reads from a pipe,so all the other commands of the loop are executed only when the child has something to read from the pipe(communicates with the parent),otherwise the child is blocked and is waiting.When the first child receives the signal from the parent,executes its signal handler function.So the parent does:

    Code:
    for(int k=0;k<numberOfProcesses;k++){
        cout<<"sending signal to "<<childpid[k]<<endl;
        kill(childpid[k],SIGUSR1);
        cout<<"Signal sent to "<<childpid[k]<<endl;
        while(!p1){
            cout<<"";
    	//sleep(1);
         }
         cout<<"finally reached here!"<<endl;
        //rest of the code you suggested
    }
    the first 2 couts are printed ok,that means the signal is sent to the child.The child on the other hand prints that it received the signal(that means child's signal handler function is executed ok).
    Then the parent never leaves its while(!p1) loop and that's because the child after executing its signal handler command doesn't return to execute the commands in its main function.Here's the child:

    Code:
    while(!c1){
    //do things while not a signal is received
    }
    cout<<"child reached this point before terminating!!!"<<endl;
    kill(getppid(),SIGUSR2); 
    cout<<"Child with pid exits "<<getpid()<<endl;
    These couts should be executed after the signal handler function but they never do.(the reason I have so many couts is to understand where is the problem).When the child gets the signal from the parent is already somewhere in the while loop.Then why it doesn't return to the first command after the loop?It seems to block and do nothing...

  9. #9
    Registered User
    Join Date
    May 2011
    Posts
    116
    actually I just realized that the child after the signal handler function returns to the main function and inside the loop(as it was already inside when it caught the signal)
    but blocks there because there's the command getline() which waits to read from the pipe.It was already blocked there when the signal arrived so it continues from the same point.
    But the thing is that the parent doesn't write anything to the pipe anymore
    The child looks like:

    Code:
    while(!c1){
    	ifstr.getline(line,LINESIZE); //reads from parent pipe
            //do things
    }
    so when the signal arrives is blocked,executes the signal handler function and returns to the same point and continues being blocked..
    Any ideas to solve that?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to get process info ( to extract process thread id )
    By umen242 in forum C++ Programming
    Replies: 4
    Last Post: 02-12-2009, 01:08 PM
  2. Child process can't send signal to itself.
    By arunj in forum C Programming
    Replies: 2
    Last Post: 03-23-2008, 11:19 AM
  3. Process sending file descriptors to another process
    By Yasir_Malik in forum C Programming
    Replies: 4
    Last Post: 04-07-2005, 07:36 PM
  4. Child Process & Parent Process Data :: Win32
    By kuphryn in forum Windows Programming
    Replies: 5
    Last Post: 09-11-2002, 12:19 PM
  5. Signal
    By Gerard Fremaint in forum A Brief History of Cprogramming.com
    Replies: 1
    Last Post: 09-10-2002, 02:03 PM