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?
相关问题
- Multiple sockets for clients to connect to
- Is shmid returned by shmget() unique across proces
- What is the best way to do a search in a large fil
- glDrawElements only draws half a quad
- Index of single bit in long integer (in C) [duplic
To me, this below line was enough to decide:
http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html#tag_03_690_07
Whether you're starting from scratch or modifying an old program, sigaction should be the right option.
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:
signal() is standard C, sigaction() is not.
If you're able to use either (that is, you're on a POSIX system), then use sigaction(); it's unspecified whether signal() resets the handler, meaning that to be portable you have to call signal() again inside the handler. What's worse is that there's a race: if you get two signals in quick succession, and the second is delivered before you reinstall the handler, you'll have the default action, which is probably going to be to kill your process. sigaction(), on the other hand, is guaranteed to use “reliable” signal semantics. You need not reinstall the handler, because it will never be reset. With SA_RESTART, you can also get some system calls to automatically restart (so you don't have to manually check for EINTR). sigaction() has more options and is reliable, so its use is encouraged.
Psst... don't tell anyone I told you this, but POSIX currently has a function bsd_signal() which acts like signal() but gives BSD semantics, which means it's reliable. Its main use is for porting old applications that assumed reliable signals, and POSIX does not recommend using it.
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.
I would also suggest using sigaction() over signal() and would like to add one more point. sigaction() gives you more options such as pid of the process that died (possible using the siginfo_t struct).
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 thatsigaction()
avoids - unless you use the flags explicitly added tosigaction()
to allow it to faithfully simulate the oldsignal()
behaviour.signal()
function does not (necessarily) block other signals from arriving while the current handler is executing;sigaction()
can block other signals until the current handler returns.signal()
function (usually) resets the signal action back toSIG_DFL
(default) for almost all signals. This means that thesignal()
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.signal()
varies between systems — and the standards permit those variations.These are generally good reasons for using
sigaction()
instead ofsignal()
. However, the interface ofsigaction()
is undeniably more fiddly.Whichever of the two you use, do not be tempted by the alternative signal interfaces such as
sighold()
,sigignore()
,sigpause()
andsigrelse()
. They are nominally alternatives tosigaction()
, 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, bothsignal()
andsigaction()
are OK in multi-threaded applications.Cornstalks observes:
That's interesting. The Linux manual page is more restrictive than POSIX in this case. POSIX specifies for
signal()
:So POSIX clearly specifies the behaviour of
signal()
in a multi-threaded application.Nevertheless,
sigaction()
is to be preferred in essentially all circumstances — and portable multi-threaded code should usesigaction()
unless there's an overwhelming reason why it can't (such as "only use functions defined by Standard C" — and yes, C11 code can be multi-threaded). Which is basically what the opening paragraph of this answer also says.