[Contents] [Prev Chap] [*] [*] [Next Chap] [Index] [(i)]

H    Early Child Exit Notification

In DIGITAL UNIX Version 4.0D, the early child exit notification feature alerts a parent process when a child process is about to dump core and exit abnormally with a signal. Because writing a core file can take an indeterminate period of time, early notification allows the parent process to take immediate action to recover from the child process' impending termination.

A parent process requests early exit notification when establishing a signal handler for the SIGCHLD signal with the sigaction system call. The sigaction flag SA_CLDNOTIFY requests early notification; you should use this flag in combination with the SA_SIGINFO flag to provide complete information about the terminating child.

Setting the SA_CLDNOTIFY flag in combination with SA_SIGINFO causes two SIGCHLD signals to be sent to the parent for each abnormal termination of a child process:

  1. The early-notification signal delivers a siginfo structure with the si_signo field set to SIGCHLD, the si_code field set to CLD_SIGEXITING, and the si_pid field set to the process ID of the child process that is about to write a core file and terminate abnormally. This signal tells the parent process that it can start its failover operation or take other appropriate action.

  2. The final-notification signal delivers a siginfo structure with the si_signo field set to SIGCHLD, the si_code field set to CLD_DUMPED, and the si_pid field set to the process ID of the child that has terminated abnormally. This signal tells the parent process that the child process is now a zombie and should be cleaned with a call to wait.

Note that the use of SA_CLDNOTIFY in the recommended combination with SA_SIGINFO in effect turns the SIGCHLD signal into a "realtime" signal. Every instance of the SIGCHLD signal is queued first-in, first-out to the parent process. Every early child exit and every final child exit generates a SIGCHLD signal to the parent. Contrast this behavior with the default behavior of the SIGCHLD signal, in which multiple child exit signals can be compressed into a single signal when the SIGCHLD signal is already pending for the parent process.

The following program shows an example of using early notification of child process termination.

        #include <stdio.h>
        #include <sys/types.h>
        #include <sys/signal.h>
        #include <sys/siginfo.h>

 
volatile pid_t kid1, kid2;
 
/* * Handler for SIGCHLD signal. Note: printf() calls * are technically unsupported from signal handlers * and are shown for illustrative purposes only. */ void sigchld_handler(int sig, siginfo_t *sip, void *extra) { pid_t kid; kid = sip->si_pid; if (sip->si_code == CLD_SIGEXITING) { printf("SIGEXITING: Got signal %d, si_code %d" " for kid %d\n", sip->si_signo, sip->si_code, kid); } else if (sip->si_code == CLD_DUMPED) {
 
printf("EXITED: Got signal %d, si_code %d" " for kid %d\n", sip->si_signo, sip->si_code, kid); kid = wait(0); printf("Parent got PID %d exiting\n", kid); if (kid == kid1) kid1 = 0; else if (kid == kid2) kid2 = 0; } }
 
main() { struct sigaction sa; int ret;
 
/* * Set up SIGCHLD handler for early exit * notification. */ sa.sa_sigaction = sigchild_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_CLDNOTIFY|SA_SIGINFO;
 
ret = sigaction(SIGCHLD, &sa, 0); if (ret) { perror("sigaction"); exit(1); }
 

 
/* * Create 2 children to die with SIGABRT * and create core files. */ kid1 = fork(); if (kid1) printf("Parent forked %d\n", kid1); else { /* * First child... */ sleep(1); printf("Kid %d will now die with core file...\n", getpid()); abort(); /*NOTREACHED*/ } kid2 = fork(); if (kid2) printf("Parent forked %d\n", kid2); else { /* * Second child... */ sleep(1); printf("Kid %d will now die with core file...\n", getpid()); abort(); /*NOTREACHED*/ }
 
/* * Parent: keep busy until children exit. */ while (kid1 || kid2) ; ; /* * Children have exited: verify by printing zeros. */ printf("Parent: done -- kid1 %d, kid2 %d\n", kid1, kid2); ; /* * Children have exit: verify by printing zeros. */ printf("Parent: done -- kid1 %d, kid2 %d\n", kid1, kid2); }