SYS V SIGCLD Handling

Conor P. Cahill cpcahil at virtech.uucp
Wed Nov 22 00:29:42 AEST 1989


In article <DOUGM.89Nov20182829 at queso.ico.isc.com>, dougm at queso.ico.isc.com (Doug McCallum) writes:
> In article <1989Nov20.124459.26023 at virtech.uucp> cpcahil at virtech.uucp (Conor P. Cahill) writes:
>    Yes.  You need to wait for the child in the handler.  If you have more
>    than one possible child, you need to wait for however many of them
>    there could be (usually you use alarm() to time out the wait).
> 
> You only need to wait for one child in the signal handler.  With SYSV,
> the SIGCLD handler will be called once for each child process that
> dies.  By waiting for just one and returning, you will get called for
> each exiting child with no need to timeout with an alarm.

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.

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.  So you can get away with a single wait() under system V.

The following program will demonstrate the handling of SIGCLDs under systemV.

#include	<stdio.h>
#include	<signal.h>

main()
{
	int 	pid;
	void	signal_handler();
	signal(SIGCLD,signal_handler);

	if( (pid=fork()) == 0 )
	{
		sleep(2);
		printf("1st child exiting\n");
		exit(10);
	}
	fprintf(stdout,"Process %d started...\n", pid);
	fflush(stdout);
	if( (pid=fork()) == 0 )
	{
		sleep(2);
		printf("2nd child exiting\n");
		exit(10);
	}
	fprintf(stdout,"Process %d started...\n", pid);
	fflush(stdout);
	if( (pid=fork()) == 0 )
	{
		sleep(5);
		printf("3rd child exiting\n");
		exit(10);
	}
	fprintf(stdout,"Process %d started...\n", pid);
	fflush(stdout);
	sleep(20);

}

void
signal_handler()
{
	int pid;
	printf("in signal handler...\n");
	sleep(10);
	pid = wait((int*)0);
	printf("process %d exited\n",pid);
	signal(SIGCLD,signal_handler);
	printf("leaving signal handler...\n");
}


OUTPUT from this program:

	Process 29771 started...
	Process 29772 started...
	Process 29773 started...
	1st child exiting
	2nd child exiting
	in signal handler...
	3rd child exiting
	process 29773 exited
	in signal handler...
	process 29772 exited
	in signal handler...
	process 29771 exited
	leaving signal handler...
	leaving signal handler...
	leaving signal handler...

Note the multiple layers of the signal handler.  Apparrently the call to
signal() enables the receipt of further SIGCLDs.

If you change the wait code to look like:

	while( (pid = wait((int*)0)) != -1)
		fprintf(...

The output will be as follows:

	Process 29784 started...
	Process 29785 started...
	Process 29786 started...
	1st child exiting
	2nd child exiting
	in signal handler...
	3rd child exiting
	process 29786 exited
	process 29785 exited
	process 29784 exited
	leaving signal handler...

Note that all three processes are handled by the wait() loop and no further
SIGCLDs are received.
 
-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+



More information about the Comp.unix.questions mailing list