Free since 2005 · No login required
AT

Academic Tutorials

Learn at your own pace

site-mobile-top-banner · 320x50

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)(int signal_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(int signal_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(int signal_number, int interrupt);

Alter the SV_INTERRUPT property of a signal handler. If interrupt is zero, system calls will be restarted after signal delivery. If it is non-zero they will return EINTR.

int sigsetmask(int new_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(int signal_mask);

Add a new set of signals to the current signal mask.

int sigpause(int signal_mask);

Wait for a signal using the given signal mask.

The sigvec structure defines the signal-handling semantics:

struct sigvec { int (*sv_handler)(void); /* signal handler */ int sv_mask; /* signals to mask during signal delivery */ int sv_flags; /* signal delivery options */ };

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