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