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:
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.
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); }