kill signal example

25,806

Your code has a major race condition. You do not ensure that the child has finished calling signal before the parent sends the signals. You either need to use some kind of synchronization primitive to make the parent wait for the child to install the handlers, or you need to install the signal handlers before forking so the child inherits them.

Here's the easiest way I know to synchronize processes like this:

  1. Before forking, call pipe(p) to create a pipe.
  2. fork().
  3. In the parent, close(p[1]); (the writing end) and read(p[0], &dummy, 1);
  4. In the child, close(p[0]); and close(p[1]); after installing the signal handlers.
  5. When the parent returns from read, you can be sure the child has setup its signal handlers. You can also close(p[0]); in the parent at this point.

Edit 2: Perhaps a better and easier approach:

  1. Before forking, call sigprocmask to block all signals and save the old signal mask.
  2. In the parent, call sigprocmask again right after forking to restore the original signal mask.
  3. In the child, call sigprocmask right after installing the signal handlers to restore the original signal mask.
Share:
25,806
Christian Wagner
Author by

Christian Wagner

Updated on December 19, 2020

Comments

  • Christian Wagner
    Christian Wagner over 3 years

    I'm trying this example that I took from: http://www.cs.cf.ac.uk/Dave/C/node24.html:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    
    void sighup(); /* routines child will call upon sigtrap */
    void sigint();
    void sigquit();
    
    main() { 
     int pid;
    
     /* get child process */
    
     if ((pid = fork()) < 0) {
        perror("fork");
        exit(1);
     }
    
    if (pid == 0) { /* child */
       printf("\nI am the new child!\n\n");
           signal(SIGHUP,sighup); /* set function calls */
           signal(SIGINT,sigint);
           signal(SIGQUIT, sigquit);
           printf("\nChild going to loop...\n\n");
          for(;;); /* loop for ever */
     }
    else /* parent */
     {  /* pid hold id of child */
       printf("\nPARENT: sending SIGHUP\n\n");
       kill(pid,SIGHUP);
       sleep(3); /* pause for 3 secs */
       printf("\nPARENT: sending SIGINT\n\n");
       kill(pid,SIGINT);
       sleep(3); /* pause for 3 secs */
       printf("\nPARENT: sending SIGQUIT\n\n");
       kill(pid,SIGQUIT);
       sleep(3);
     }
    }
    
    void sighup() {
       signal(SIGHUP,sighup); /* reset signal */
       printf("CHILD: I have received a SIGHUP\n");
    }
    
    void sigint() {
        signal(SIGINT,sigint); /* reset signal */
        printf("CHILD: I have received a SIGINT\n");
    }
    
    void sigquit() {
      printf("My DADDY has Killed me!!!\n");
      exit(0);
    }
    

    But I do not see any output from the child process.

    Is it the expected behaviour? If so; why?

    Thank you very much!

  • danglingpointer
    danglingpointer almost 7 years
    OP, mentioned no output from the child process(). getpid() will only give the id of the process. will that solve the problem?