Sunday 22 November 2015

Using PR_SET_PDEATHSIG to reap child processes

The prctl() system call provides a rather useful PR_SET_PDEATHSIG option to allow a signal to be sent to child processes when the parent unexpectedly dies. A quick and dirty mechanism is trigger the SIGHUP or SIGKILL signal to kill the child immediately, or perhaps more elegantly to invoke a resource tidy up before exiting.

In the trivial example below, we use the SIGUSR1 signal to inform the child that the parent has died. I know printf() should not be used in a signal handler, it just makes the example simpler.

 #include <stdlib.h>                                 
 #include <unistd.h>                                 
 #include <signal.h>                                 
 #include <sys/prctl.h>                               
 #include <err.h>                                  
                                           
 void sigusr1_handler(int dummy)                           
 {                                          
     printf("Parent died, child now exiting\n");                 
     exit(0);                                  
 }                                          
                                           
 int main()                                     
 {                                          
     pid_t pid;                                 
                                           
     pid = fork();                                
     if (pid < 0)                                
         err(1, "fork failed");                       
     if (pid == 0) {                               
         /* Child */                             
         if (signal(SIGUSR1, sigusr1_handler) == SIG_ERR)          
             err(1, "signal failed");                  
         if (prctl(PR_SET_PDEATHSIG, SIGUSR1) < 0)              
             err(1, "prctl failed");                   
                                           
         for (;;)                              
             sleep(60);                         
     }                                      
     if (pid > 0) {                               
         /* Parent */                            
         sleep(5);                              
         printf("Parent exiting...\n");                   
     }                                      
                                           
     return 0;                                  
 }   

..the child process sits in an infinite loop, performing 60 second sleeps.  The parent sleeps for 5 seconds and then exits.  The child is then sent a SIGUSR1 signal and the handler exits.  In practice the signal handler would be used to trigger a more sophisticated clean up of resources if required.

Anyhow, this is a useful Linux feature that seems to be overlooked.

No comments:

Post a Comment