UNIX Signal Handling Environments
Added 31 Jul 2008
There are four common signal-handling environments today. They are BSD, System-V unreliable, System-V reliable, and POSIX. This section discusses each and common variations where appropriate.
The Traditional System-V Signal Environment
Traditional System-V inherited its signal-handling environment from V7 research UNIX. This environment has three major limitations:
- Recursive signal handling is always allowed.
- Signal handlers are reset to SIG_DFL prior to being called.
- System calls interrupt when a signal is delivered.
These limitations cause "unreliable" signal behavior: Since signals can be delivered recursively and the signal handler must manually reset the signal handler from SIG_DFL, there is a window during which the default signal handler can be called if another signal of the same type arrives. In many cases the default action is to ignore the signal, causing the signal to be lost. In the worst case the default action is to terminate the process.
Additionally any signal can interrupt a system call. The window for interrupting a system call is fairly small for most system calls (and impossible for some) but large for some common "slow" system calls such as read() or write(). Few applications attempt to restart system calls that have been interrupted by a signal. This results in even more unreliability.
The interface to the traditional signal handling environment is:
int (*signal)(intsignal_number, int (*function)(int));- Change the signal handler for the indicated signal.
Signal_number indicates which signal, function is the
new handler.
int pause(void);- Wait for a signal to arrive.
Two standard signal handlers exist:
SIG_DFL- Take the default action for this signal.
SIG_IGN- Ignore this signal.
The BSD 4.X Signal Environment
Because of the problems inherent in V7 signal handling, the BSD developers modified the signal-handling semantics somewhat:
- Signals are blocked for the duration of a signal handler (i.e. recursive signals are not normally allowed).
- A "signal mask" can be set to block most signals during critical regions.
- Signal handlers normally remain installed during and after signal delivery.
- A separate signal handler stack can be used if desired.
- Most system calls are restarted following delivery of a signal.
This worked around the "unreliable" semantics of traditional System-V signal handling and added critical-section protection at the same time. Both are essential for reliable applications.
The BSD interface includes the traditional System-V interface (using the new reliable semantics) but adds the following:
int sigvec(intsignal_number, struct sigvec *new_sigvec, struct sigvec *old_sigved);- Change or query signal handlers. Signal_number indicates
which signal. New_sigvec defines the handler environment or
may be null if you don't want to change the handler. If non-null,
old_sigvec is filled with the current handler information.
int sigstack(char *stack);- Change the stack which will be used during signal delivery.
int siginterrupt(intsignal_number, intinterrupt);- Alter the
SV_INTERRUPTproperty of a signal handler. If interrupt is zero, system calls will be restarted after signal delivery. If it is non-zero they will returnEINTR. int sigsetmask(intnew_mask);- Change the set of masked/held signals. New_mask is a bit
pattern describing the new set of signals. The old signal mask is
returned.
int sigblock(intsignal_mask);- Add a new set of signals to the current signal mask.
int sigpause(intsignal_mask);- Wait for a signal using the given signal mask.
The sigvec structure defines the signal-handling
semantics:
The sv_flags field describes the options you could use to alter signal handling. Standard options are:
SV_ONSTACK- Use a special stack rather than the normal hardware stack. The
stack to use must be specified using
sigstack(). SV_RESETHAND- Use V7-style "reset to default handler" signal handling
semantics.
SV_INTERRUPT- Allow system calls to be interrupted by signal delivery.
Not all of these options are supported by "BSD-compatible" systems
and SV_RESETHAND was not supported until BSD 4.3.
The same set of standard signal handlers is used as in V7 and traditional Sys