Department of Electrical and Computer Engineering
Dalhousie University

Introduction to Signals

Dr. Larry Hughes


Introduction

There are a number of ways in which an external event can be supplied to a process. One approach is to make the process query the kernel explicitly to determine if the event had taken place (essentially polling for the event).

Another approach, supported by most operating systems, is for the kernel (or a process) to call a subroutine specified by a running process when an event occurs. The event, usually referred to as a signal, is thrown to the subroutine, sometimes referred to as a catcher.

Signals can be looked upon as interrupts which are handled by a process. The process is interrupted and control passes to the catcher, which performs a set of instructions associated with the signal. When the catcher has completed its task, control returns to the process.

Most operating systems support a wide range of signals, some are used for interprocess communication, while others handle software faults that occur within the running process.

Since most applications (running as processes) have little interest in handling signals, all signals are associated with default actions (often terminating the running process). Processes can also choose to ignore signals (there are usually restrictions placed upon this, since fatal actions, such as memory violation, usually indicate that there is something wrong with the application).

Signals

There are a wide range of signals (most versions of Unix support thirty or more); some common signals include:

SignalMeaning
SIGBRKBreak detected from keyboard
SIGABRTAbnormal termination
SIGFPEFloating point exception
SIGILLIllegal opcode
SIGINTControl-C interrupt detected from keyboard
SIGSEGVIllegal memory access
SIGTERMRequest for program termination

Note in keeping with the Unix approach of capitalizing defined constants, all signals are in capital letters.

Support

There are a number of functions available for signal handling, some are listed here.

signal(signal, action)

The function signal() allows a process to indicate what action is to take place when a specific signal occurs. The signal is an operating system specific signal (for example, see above). The action is the name of a function which is to be called if the signal occurs. For example, to catch SIGABRT, one could write the following:

void catch_abort()
{
/* Code to handle SIGABRT */
}
 
main()
{
...
signal(SIGABRT, catch_abort);
...
}

Some applications may choose to explicitly ignore a signal, while others may require the action to revert back to the system default action. There are two 'functions' available for this action:

FunctionAction
SIG_DFLPeforms the default action associated with the signal
SIG_IGNIgnores the signal should it occur

For example, to ignore any system-defined actions for SIGABRT, one could write:

main()
{
...
signal(SIGABRT, SIG_IGN);
...
}

If the SIGABRT signal should occur, it is ignored by this process.

raise(signal)

A process can throw a signal to itself using the raise() function. The signal specified will result in whatever action the application has requested for the signal.

Raise() can be used in various situations, including the testing of catchers or indicating to a process that a specific set of instructions have been executed (i.e., debugging).

kill(pid, signal)

The kill() function allows one process to send a signal to another. Kill() might seem like a misnomer, but in most early versions of Unix, this function was associated with SIGTERM (terminate a specific process).


© 2003 - Whale Lake Press