SYS V SIGCLD Handling
Chris Torek
chris at mimsy.umd.edu
Wed Nov 22 08:57:27 AEST 1989
In article <1989Nov21.132942.29972 at virtech.uucp> cpcahil at virtech.uucp
(Conor P. Cahill) writes:
>The documentation states that SIGCLDs received while a process is in the
>SIGCLD signal handler will be ignored. That sounds like you could miss
>a SIGCLD or two.
The documentation (almost) lies.
SIGCLD is, in System V, not a signal. Oh, it has a signal number, and
can be generated by kill(2), and can be caught by signal(2), and so
forth. But it is not a signal. It is a weird thing that happens to
use some of the existing signal code so as to avoid inventing a new
facility, while at the same time being very un-signal-like in its
behaviour. (Just like SIGCONT in BSD, actually....)
>In testing, I found that while the SIGCLD is ignored in the signal handler,
>once the handler executes signal(SIGCLD,handler), if there are any child
>processes that have exited and have not yet been waited for, another SIGCLD
>is generated.
Right. Unlike all other signals, SIGCLD is `regenerative.' (It is NOT
queued, despite reports of claims to that effect in other parts of
System V documentation.) Instead, there is special code in the
signal() system call to check to see if the action for SIGCLD is being
altered. If so, one of the following is true:
a) SIGCLD is being set to SIG_IGN.
In this case, all zombie (exited) children of the current process are
flushed as if by a series of calls to wait(2).
b) SIGCLD is being set to SIG_DFL.
In this case, do nothing.
c) SIGCLD is being set to a catch function.
In this case, one (1) SIGCLD signal is immediately posted (via psignal(),
if the kernel function has the same name as the one in BSD).
Meanwhile, there is a second special case in the kernel, in exit(): If
u.u_signal[SIGCLD]==SIG_IGN, the newly dead process is discarded
immediately. Otherwise, a SIGCLD signal is sent (possibly optional on
u.u_signal[SIGCLD]!=SIG_DFL---this would simply be an optimisation).
There is no third special case. *All* signals are reset to SIG_DFL on
actual delivery, including SIGCLD.
Thus, the `proper' way to catch SIGCLD in SysV is:
void catch(int sig) {
int w, status;
do { w = wait(&status); } while (w==-1 && errno==INTR);
<<< do something with w and status >>>
(void) signal(SIGCLD, catch);/* recurses if necessary */
}
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: chris at cs.umd.edu Path: uunet!mimsy!chris
More information about the Comp.unix.questions
mailing list