(A UN*X signal:)
SIGCHLD (called SIGCLD on SysV (spit!) -derived Unices (but it doesn't matter, because usually a modern system will #define one and #define the other as an alias) is the "child process terminated" signal on UNIX, Linux, and the other Unixoids. It is sent to the parent process of a fork() when the child process terminates for any reason. As the child process can be completely uncoordinated with its parent (indeed, a very common case is to fork-and-exec, which is how a process runs some other command as its subprocess), the signal is inherently asynchronous.
The signal is usually SIG_IGNored -- processes must explicitly request notification for this event. Upon receipt of the signal, the process knows that one or more subprocesses have terminated. This is a general characteristic of UNIX signals: There is no count associated with the signal, so the receiving process cannot know how many events have occurred -- only that there was at least one occurrence. (Of course, a process which only fork()s once will know that only one child process terminated!)
The typical action in response to SIGCHLD is to call one of the wait*() functions (wait(), waitpid(), and especially the aptly-named wait3() and wait4() are all common) to determine what happened to the child. Information returned is the process' exit code or the signal which caused its termination. As the parent process generally has no idea how many children terminated, it will typically call wait3() or wait4() in a loop, until notified that no further children have terminated. This also prevents zombies from accumulating. (So you must either trap SIGCHLD to call wait*()s, or do a blocking wait for every fork() to prevent them.)
Here's one way to see SIGCHLD live in action. Normally, a UNIX shell wait()s for the current foreground process, then wait3()s or wait4()s in a loop for any background processes which terminated before displaying the next prompt. So all terminated processes are reported just before the next prompt:
% unset notify
% date &
[1] 30823
Sat May 31 12:00:30 UTC 2003
% echo next command
next command
[1] Done date
%
We tell the shell
not to
notify us asynchronously of child process termination. Then we run date in the background; as we see, it terminates even before we manage to type in the next command, but we receive no report. Only after the next "
echo" command completes does the shell wait*() for any background processes, and discovers that date has finished running.
However, if we enable asynchronous notifications:
% set notify
% date &
[1] 30826
Sat May 31 12:03:44 UTC 2003
[1] Done date
% (sleep 5; date)&
[1] 30827
% echo done
done
% Sat May 31 12:03:58 UTC 2003
[1] Done ( sleep 5; date )
% echo 1 2 3
1 2 3
%
Now we asked the shell to
notify us immediately. Indeed, the first
date command terminates before we can do anything interesting, and we're notified. To get a better notion of asynchronousness, we ask the shell to
sleep 5 seconds before running date -- all in the background. This time, we manage to give one echo command before the date is printed; but halfway into typing the second "echo 1 2 3" command the process terminates, the date is printed, and we receive a report of what happened. SIGCHLD is at work here,
behind the scenes.