Subject: Re: Sane exit from a program on receipt of a signal
To: Christos Zoulas <christos@zoulas.com>
From: Luke Mewburn <lukem@NetBSD.org>
List: tech-userlevel
Date: 09/24/2007 13:34:58
--JP+T4n/bALQSJXh8
Content-Type: multipart/mixed; boundary="0OAP2g/MAC+5xKAE"
Content-Disposition: inline


--0OAP2g/MAC+5xKAE
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Jul 25, 2007 at 10:36:39AM -0400, Christos Zoulas wrote:
  | 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.

How's this?


cheers,
Luke.

--0OAP2g/MAC+5xKAE
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="raise_default_signal.c"

/*	$NetBSD$	 */

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <util.h>

/*
 * raise_default_signal sig
 *	Raise the default signal handler for sig, by
 *	- block all signals
 *	- set the signal handler to SIG_DFL
 *	- raise the signal
 *	- unblock the signal to deliver it
 *
 *	The original signal mask and signal handler is restored on exit
 *	(whether successful or not).
 *
 *	Returns -1 on failure, 0 on success, with errno set to
 *	on of the values for sigemptyset(), sigaddset(), sigprocmask(),
 *	sigaction(), or raise().
 */
int
raise_default_signal(int sig)
{
	struct sigaction origact, act;
	sigset_t origmask, fullmask, mask;
	int retval, oerrno;

	retval = -1;

		/* Setup data structures */
	memset(&act, 0, sizeof(act));	/* XXX not async safe per signal(7) */
	act.sa_handler = SIG_DFL;
	act.sa_flags = 0;
	if ((sigemptyset(&act.sa_mask) == -1) ||
	    (sigfillset(&fullmask) == -1) ||
	    (sigemptyset(&mask) == -1) ||
	    (sigaddset(&mask, sig) == -1))
		goto restore_none;

		/* Block all signals */
	if (sigprocmask(SIG_BLOCK, &fullmask, &origmask) == -1)
		goto restore_none;
		/* (use 'goto restore_mask' to restore state) */

		/* Enable the SIG_DFL handler */
	if (sigaction(sig, &act, &origact) == -1)
		goto restore_mask;
		/* (use 'goto restore_act' to restore state) */

		/* Raise the signal, and unblock the signal to deliver it */
	if ((raise(sig) == -1) ||
	    (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1))
		goto restore_act;

		/* Flag successful raise() */
	retval = 0;

		/* Restore the original handler */
 restore_act:
	oerrno = errno;
	(void)sigaction(sig, &origact, NULL);
	errno = oerrno;

		/* Restore the original mask */
 restore_mask:
	oerrno = errno;
	(void)sigprocmask(SIG_SETMASK, &origmask, NULL);
	errno = oerrno;

 restore_none:
	return retval;
}

--0OAP2g/MAC+5xKAE--

--JP+T4n/bALQSJXh8
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (NetBSD)

iD8DBQFG9zBipBhtmn8zJHIRAjxiAJ9P3JyNs1fbhXtwpBo/IId3MMkvgwCguzgW
S8n2IB4orz3uLN8L/rl2MRs=
=f3U+
-----END PGP SIGNATURE-----

--JP+T4n/bALQSJXh8--