Saturday, October 11, 2014

Unix Prog: SIGCLD Semantics

1. SIGCLD in old systems

The older handling of SIGCLD:
1) If the process specifically sets its disposition to SIG_IGN, children of the calling process will not generate zombie processes. It means, after children processes terminate, all status information will be discarded. If the calling process calls wait, the calling process will block until all children have terminated and then wait return -1 with errno set to ECHILD.

2) If we set the disposition of SIGCLD to be caught, the kernel immediately checks whether any child processes are ready to be waited for and, if so, calls the SIGCLD handler.

2. Example of setting up the disposition of SIGCLD to be caught:

sigcld.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<signal.h>  
 #include<sys/wait.h>  
   
 static void sig_cld(int signo)  
 {  
  pid_t pid;  
  int status;  
   
  printf("SIGCLD received\n");  
  if(signal(SIGCLD, sig_cld) == SIG_ERR) {  
   printf("signal error!\n");  
   exit(2);  
  }  
  if((pid = wait(&status)) < 0) {  
   printf("wait error!\n");  
   exit(3);  
  }  
   
  printf("pid = %d\n", pid);  
 }  
   
 int main(int argc, char *argv[])  
 {  
  pid_t pid;  
   
  if(signal(SIGCLD, sig_cld) == SIG_ERR) {  
   printf("signal error!\n");  
   exit(1);  
  }  
   
  if((pid = fork()) < 0) {  
   printf("fork error!\n");  
   exit(2);  
  } else if(pid == 0) { /* child process */  
   sleep(2);  
   _exit(0);  
  }  
   
  pause();  
  exit(0);  
 }  

shell:
In current system, after child process terminated, the SIGCLD is successfuly sent to parent process.
Inside the signal handler, we immediately re-establish the SIGCLD handler, since in old implementation, the signal disposition is reset to default every time it is caught.
Also, in old system, every time the calling process re-establish the SIGCLD handler, the kernel will check the terminated children process immediately and if there is, send out the SIGCLD signal.
In this case, the calling process will fall into one endless loop to keep getting the SIGCLD signal, run signal handler, re-establish handler, and kernel send out SIGCLD signal again.
 ubuntu@ip-172-31-23-227:~$ ./sigcld.out  
 SIGCLD received  
 pid = 20779  

No comments:

Post a Comment