Subject: Re: Sane exit from a program on receipt of a signal
To: None <firstname.lastname@example.org>
From: Christos Zoulas <email@example.com>
Date: 07/18/2007 20:27:35
In article <20070718020949.GD958@mewburn.net>,
Luke Mewburn <lukem@NetBSD.org> wrote:
>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
>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?
> 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))
- It should return int with an error.
- I think that you want to make sure that you exit with that signal and
not another. See: /usr/src/lib/libc/sys/stack_protector.c
- call it raise4sure() :-) or raise_default_unblock()?