Signals are inherently global. There are two ways to handle a signal with external values.
- Put the external data in a global variable and access it from the signal handler.
- Put the signal data in a global variable and access it from the program context.
This post covers the second option. The signal handler is an isolated part of the program. The first option can be made to work, but exposing a lot of global state is inelegant.
The signal_handler module covered in this post consists of five functions.
registerSignalHandler() takes a null terminated array of signals to handle, and registers the signal handler with each one. signalHandler() actually responds to the signal. When a signal is trapped, a flag is set and the signal number is recoreded. clearSignal() clears the flag and signal value. pendingSignal() returns true if the signal flag is set. getSignal() returns the signal value. If multiple signals are trapped in rapid succession, the signal value will be overwritten. A more robust solution would have a flag for every signal.
The function bodies follow. Note that gInterrupt and gSignal can only be polled or reset by the outside world. syslog or printf can be used to log signal events.
The signal handler can be registered during initialization. This is also a good place to clear the signal state for the fist time.
The signal handler module can be used to write a parameterized function that responds to signals. The following function does not do anything unless a pending signal needs to be handled. A switch statement can be used to provide different handling for different signals. This version just sets a done flag to true. Finally, the signal state is cleared.
The above function can be called any place that is convenient. For example, the following function calls the above signalResponse() function every iteration of the main loop. The program can trap signals and clean up gracefully
Note that the simple example below has a bug. getchar() blocks, so the signalResponse() handler will not be called until after user input. If the user hits ^C, the loop (and program) will not exit until the user hits enter.