400 Chapter 20
Listing 20-1 (on page 399) shows a simple example of a signal handler function and
a main program that establishes it as the handler for the SIGINT signal. (The termi-
nal driver generates this signal when we type the terminal interrupt character, usually
Control-C.) The handler simply prints a message and returns.
The main program continuously loops. On each iteration, the program incre-
ments a counter whose value it prints, and then the program sleeps for a few sec-
onds. (To sleep in this manner, we use the sleep() function, which suspends the
execution of its caller for a specified number of seconds. We describe this function
in Section 23.4.1.)
When we run the program in Listing 20-1, we see the following:
$ ./ouch
0 Main program loops, displaying successive integers
Type Control-C
Ouch! Signal handler is executed, and returns
1 Control has returned to main program
2
Type Control-C again
Ouch!
3
Type Control-\ (the terminal quit character)
Quit (core dumped)
When the kernel invokes a signal handler, it passes the number of the signal that
caused the invocation as an integer argument to the handler. (This is the sig argu-
ment in the handler of Listing 20-1). If a signal handler catches only one type of signal,
then this argument is of little use. We can, however, establish the same handler to
catch different types of signals and use this argument to determine which signal
caused the handler to be invoked.
This is illustrated in Listing 20-2, a program that establishes the same handler
for SIGINT and SIGQUIT. (SIGQUIT is generated by the terminal driver when we type the
terminal quit character, usually Control-\.) The code of the handler distinguishes
the two signals by examining the sig argument, and takes different actions for each
signal. In the main() function, we use pause() (described in Section 20.14) to block
the process until a signal is caught.
The following shell session log demonstrates the use of this program:
$ ./intquit
Type Control-C
Caught SIGINT (1)
Type Control-C again
Caught SIGINT (2)
and again
Caught SIGINT (3)
Type Control-\
Caught SIGQUIT - that's all folks!
In Listing 20-1 and Listing 20-2, we use printf() to display the message from the sig-
nal handler. For reasons that we discuss in Section 21.1.2, real-world applications
should generally never call stdio functions from within a signal handler. However, in