tags:

views:

2867

answers:

4

I was about to add an extra signal handler to an app we have here and I noticed that the author had used sigaction to set up the other signal handlers. I was going to use signal. To follow convention I should use sigaction but if I was writing from scratch, which should I choose?

+2  A: 

I'd use signal() since it's more portable, in theory at least. I'll vote up any commenter who can come up with a modern system that doesn't have a POSIX compatibility layer and supports signal().

Quoting from the GLIBC documentation:

It's possible to use both the signal and sigaction functions within a single program, but you have to be careful because they can interact in slightly strange ways.

The sigaction function specifies more information than the signal function, so the return value from signal cannot express the full range of sigaction possibilities. Therefore, if you use signal to save and later reestablish an action, it may not be able to reestablish properly a handler that was established with sigaction.

To avoid having problems as a result, always use sigaction to save and restore a handler if your program uses sigaction at all. Since sigaction is more general, it can properly save and reestablish any action, regardless of whether it was established originally with signal or sigaction.

On some systems if you establish an action with signal and then examine it with sigaction, the handler address that you get may not be the same as what you specified with signal. It may not even be suitable for use as an action argument with signal. But you can rely on using it as an argument to sigaction. This problem never happens on the GNU system.

So, you're better off using one or the other of the mechanisms consistently within a single program.

Portability Note: The basic signal function is a feature of ISO C, while sigaction is part of the POSIX.1 standard. If you are concerned about portability to non-POSIX systems, then you should use the signal function instead.

Copyright (C) 1996-2008 Free Software Foundation, Inc.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".

bmdhacks
+3  A: 

From the signal(3) man page:

DESCRIPTION

 This signal() facility is a simplified interface to the more
 general sigaction(2) facility.

Both invoke the same underlying facility. You should presumably not manipulate the response the a single signal with both, but mixing them shouldn't cause anything to break...

dmckee
That's not in my man page! All I get is "DESCRIPTION The signal() system call installs a new signal handler for the signal with number signum. " I need to upgrade to the _useful_ man pages package.
MattSmith
That's off of the Mac OS X 10.5 pages.
dmckee
Also verified from the source code of glibc. signal() just calls sigaction()
bmdhacks
+3  A: 

They're different interfaces for OS's signal facilities. One should prefer using sigaction to signal if possible as the signal() has implementation-defined (often race prone) behavior and behaves differently on Windows, OS X, Linux and other UNIX systems.

See this security note for details.

ididak
I just looked at the glibc source code and signal() just calls into sigaction(). Also see above where the MacOS man page claims the same.
bmdhacks
that is good to know. I've only ever seen signal handlers used to close things neatly before exiting so I wouldn't usually be relying on behaviour to do with reinstalling the handler.
MattSmith
+17  A: 

Use sigaction() unless you've got very compelling reasons not to do so.

The signal() interface has antiquity (and hence availability) in its favour, and it is defined in the C standard. Nevertheless, it has a number of undesirable characteristics that sigaction() avoids - unless you use the flags explicitly added to sigaction() to allow it to faithfully simulate the old signal() behaviour.

  1. The signal() function does not block other signals from arriving while the current handler is executing; sigaction() can block other signals until the current handler returns.
  2. The signal() function resets the signal action back to SIG_DFL (default) for almost all signals. This means that the signal() handler must reinstall itself as its first action. It also opens up a window of vulnerability between the time when the signal is detected and the handler is reinstalled during which if a second instance of the signal arrives, the default behaviour (usually terminate, sometimes with prejudice - aka core dump) occurs.

These are generally good reasons for using sigaction() instead of signal(). However, the interface of sigaction() is undeniably more fiddly.

Whichever of the two you use, do not be tempted by the alternative signal interfaces such as sighold(), sigpause(), sigignore() and sigrelse(). They are nominally alternatives to sigaction(), but they are only barely standardized and are present in POSIX for backwards compatibility rather than for serious use. Note that the POSIX standard says their behaviour in multi-threaded programs is undefined.

(Multi-threaded programs and signals is a whole other complicated story. AFAIK, both signal() and sigaction() are OK in multi-threaded applications.)

Jonathan Leffler