When you want to set signal handlers on UNIX systems, the typical choice is to use
signal (specified in C89, C99 and POSIX.1-2001) or
sigaction (specified in POSIX.1-2001 and System V r4).
signal manual page:
The only portable use of
signal()is to set a signal’s disposition to
SIG_DFL or SIG_IGN. The semantics when using
signal()to establish a signal handler vary across systems (and POSIX.1 explicitly permits this variation); do not use it for this purpose. POSIX.1 solved the portability mess by specifying
sigaction(2), which provides explicit control of the semantics when a signal handler is invoked; use that interface instead of
Then it goes on about the UNIX vs BSD semantics, and how they affect signal delivery, which essentially is the main reason why one would want to stop using
signal and use
sigaction instead, with specifically chosen flags.
But this is not really what I wanted to talk about here.
One of the uses of
sigaction is to temporarily set a signal handler and restore the old signal handler once the job is done. Notwithstanding the fact that it’s a pretty horrible thing to do in a multi-threaded program, it’s also a horrible thing to do at all with
sigaction is used.
The core of the problem is the following: the information you get from
signal() about the old signal handler is missing all the important pieces about it if it was originally set with
sigaction(), namely, flags, masks and restorer.
So if you do use
signal() to temporarily set a signal handler and then restore the previous signal handler, you risk resetting flags, masks and restorer. The first awful thing this means is the previous signal handler might be expecting three arguments, only one of which will be valid when it’s invoked. Unexpected things can also happen with the lack of expected flags or masks. This is why you’ll see horrible workarounds like this or that.
In short, if you do use
signal() to temporarily set a signal handler and then restore the previous signal handler, you’re doing it wrong. And if you do that in a system library or driver, thank you for screwing things up. I’m looking at you