confusion about signals

Stephen Weeks MLton@sourcelight.com
Mon, 18 Mar 2002 00:15:59 -0800


> The documentation I have says that sigsuspend takes a sigset_t *,
> and makes no statement about NULL being ok.  Also there is a race
> condition here between when the child exits and when the parent does
> sigsuspend().

I see the race, but in thinking about it again, the child exits
and the SIGCHLD is sent either before or after the parent calls
sigsuspend.  If before, then handled should be set to 1 and the
sigsuspend in the parent should block, waiting forever.  I never saw
this behavior.  If after, then the sigsuspend should resume.  Ahh --
then there is still a race as to whether the signal handler or the
fprintf runs.  That explains why it is possible to see both handled =
0 and handled = 1.

> I'm surprised at the result, but I would see what happens if you
> replace the sigsuspend() call with a sleep of 5 seconds and see what
> is going on.

I replaced the fork code with

	if (0 != fork()) {
		/* Parent.  Wait on SIGCHLD from child. */
		fprintf(stderr, "sleep = %d\n", sleep(5));
		fprintf(stderr, "handled = %d\n", handled);
	}

and now I see two behaviors.

sleep = 5
handled = 1

and

sleep = 0
handled = 1

This make sense in terms of the race between the child exiting and the
call to sleep.  If the exit is first, then we see sleep = 0.  If the
call to sleep is first, then we see sleep = 5, since it is interrupted
by the signal.


So it all makes sense now, except I don't understand why the
sigsuspend didn't block forever sometimes when it lost the race.