Signals, Part 1

Signals Basics

Signals allow a process (or the kernel) to interrupt another process.

The kernel raises signals to notify a process that one of its children

has died, that an alarm set by the process has expired, etc.... When a

process is signaled, it reacts in one of the following ways:

* Ignore the signal;

* Catch the signal (i.e., have the kernel run a user-defined

function before allowing the process to resume);

* Let the kernel perform the default action associated with the

signal.

Simple Signals

The ANSI

library defines the signal() function that has the following prototype: void * signal(int signum, void * handler); The first parameter is the signal to be handled. The second parameter is a pointer to a function of the following type: void func(); When a signal signum is raised, the kernel executes the handler function as soon as possible. Once the handler returns, the kernel resumes process execution from the point of interruption. The second parameter may take two special values: SIG_IGN and SIG_DFL. SIG_IGN indicates that the signal should be ignored; SIG_DFL instructs the kernel to perform the default action when the signal is raised. A process cannot catch the SIGSTOP and SIGKILL signals, though. Instead, kernel performs the default action associated with these signals, namely stopping the process and terminating the process, respectively. Recurrent Signals What happens when a process that is already running a handler for SIGx receives another SIGx signal? Intuitively, one would expect the kernel to interrupt the process and run the handler once more. To allow this, the handler must function properly when it's called while it's already running. Put differently, the handler must be re-entrant. However, designing re-entrant handlers is too complicated. For this reason, Linux doesn't have re-entrant handlers. The original solution to the recurring signal problem was to reset the handler to SIG_DFL before executing the user-defined handler. However, this was an ill-conceived solution; when two signals occurred quickly, each one of them was handled differently. The kernel executed the handler for the first signal and performed the default action for the second one. Consequently, the second signal would in some cases cause the process to terminate. This implementation is called "unreliable signals". Next week, we will see how the POSIX signal API solved this problem more elegantly.
What’s wrong? The new clean desk test
Join the discussion
Be the first to comment on this article. Our Commenting Policies