Subject: Sane exit from a program on receipt of a signal
To: None <>
From: Luke Mewburn <>
List: tech-userlevel
Date: 07/18/2007 12:09:49
Content-Type: multipart/mixed; boundary="8vCeF2GUdMpe9ZbK"
Content-Disposition: inline

Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

A lot of the code in our tree installs signal handlers
for various reasons, and then uses exit(3) (or a variant)
to exit the application.

The problem with this is that it doesn't allow the parent
process (usually a shell) to determine if a program
exit was caused by a (probably user initiated) signal.

This is documented in more detail at:

Rather than using exit(3) to terminate because of a user-initiated
signal, the recommended solution is to reset to the default
signal handler (SIG_DFL) and raise the signal.
	signal(sig, SIG_DFL);

The problem with that solution is if the signal mask for the
process is currently blocking sig (see sigprocmask(3)), which
is often the case within the currently executing signal handler,
then the raise(3) will be blocked.  Therefore, you have to
unblock sig in the signal mask before the raise(3).

(I noticed this during a sweep of the tree for user-code
to solve the original problem.)

I've written a helper function to encapsulate this extra
complexity, and attached it to this message.
It attempts to reset the signal handler for 'sig' to=20
the default, remove 'sig' from the sigprocmask(3), and
raise(3) 'sig'.  If the function returns, the caller
knows that the raise(3) didn't terminate the process.

Is it worth adding this "raise_default()" function to
the tree, say in util(3), to simplify re-use ?

If so, is the name acceptable?


Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="raise_default.c"

raise_default(int sig)
	struct sigaction act;
	sigset_t mask;

	/* Reset to default signal handler, clear mask, raise signal */
	memset(&act, 0, sizeof(act));
	act.sa_handler = SIG_DFL;
	if ((sigemptyset(&act.sa_mask) == 0) &&
	    (sigemptyset(&mask) == 0) &&
	    (sigaddset(&mask, sig) == 0) &&
	    (sigaction(sig, &act, NULL) == 0) &&
	    (sigprocmask(SIG_UNBLOCK, &mask, 0) == 0))


Content-Type: application/pgp-signature
Content-Disposition: inline

Version: GnuPG v1.4.7 (NetBSD)