Subject: Re: Sane exit from a program on receipt of a signal
To: Luke Mewburn <lukem@NetBSD.org>
From: Christos Zoulas <christos@zoulas.com>
List: tech-userlevel
Date: 07/25/2007 10:36:39
On Jul 25,  4:46pm, lukem@NetBSD.org (Luke Mewburn) wrote:
-- Subject: Re: Sane exit from a program on receipt of a signal

| I've thought about that, and I'm not convinced that we need to.
| 
| Here's a minor rewrite of my 2nd attempt, based on some
| feedback I received privately from a friend.
| Changes:
| 
|  * Highlight that memset() isn't technically async safe per signal(7).
|    I thought about removing it entirely, but as you & I chatted
|    privately, memset() should be safe. (why wouldn't it be??)
|    I want to avoid C99 features to zero it.
|    The function should be portable to other platforms,
|    which means we shouldn't assume BSD extensions like
|    sigaction.sa_sigaction are present to explicitly zero.
|    OTOH, autoconf can solve that problem :)
| 
|  * (Temporarily) block the signal whilst we set the default handler.
| 
|  * Raise the signal and then unblock it.
| 
| I've also renamed it to 'raise_default_signal()'
| 
| 
| 
| --3loezlmesXOUD0D5
| Content-Type: text/plain; charset=us-ascii
| Content-Disposition: attachment; filename="raise_default.c"
| 
| #include <signal.h>
| #include <stdio.h>
| #include <string.h>
| 
| int
| raise_default_signal(int sig)
| {
| 	struct sigaction act;
| 	sigset_t mask;
| 
| 		/* Block the signal */
| 	if ((sigemptyset(&mask) == -1) ||
| 	    (sigaddset(&mask, sig) == -1) ||
| 	    (sigprocmask(SIG_BLOCK, &mask, NULL) == -1))
| 		return -1;
| 
| 		/* Setup default handler */
| 	memset(&act, 0, sizeof(&act));	/* XXX not async safe per signal(7) */

That should read sizeof(act)... cast memset to void to appease lint.

| 	act.sa_handler = SIG_DFL;
| 	act.sa_flags = 0;
| 	if (sigemptyset(&act.sa_mask) == -1)
| 		return -1;
| 
| 		/* Restore the default handler, raise the signal */
| 	if ((sigaction(sig, &act, NULL) == -1) ||
| 	    (raise(sig) == -1))
| 		return -1;
| 
| 		/* Unblock the signal */
| 	if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
| 		return -1;
| 
| 	return 0;
| }

I think that it is pretty simple to cleanup so why trash the signal
disposition and mask state? And if you are going to block signals,
why not block all of them with sigfillset(), instead of blocking
just that one? Then you can unblock only the signal you want
delivered.

christos