8.4 Catching and Ignoring SignalssigactionThe sigaction function allows the caller to examine or specify the action associated with a specific signal. The sig parameter of sigaction specifies the signal number for the action. The act parameter is a pointer to a struct sigaction structure that specifies the action to be taken. The oact parameter is a pointer to a struct sigaction structure that receives the previous action associated with the signal. If act is NULL, the call to sigaction does not change the action associated with the signal. If oact is NULL, the call to sigaction does not return the previous action associated with the signal.
If successful, sigaction returns 0. If unsuccessful, sigaction returns 1 and sets errno. The following table lists the mandatory errors for sigaction.
The storage for sa_handler and sa_sigaction may overlap, and an application should use only one of these members to specify the action. If the SA_SIGINFO flag of the sa_flags field is cleared, the sa_handler specifies the action to be taken for the specified signal. If the SA_SIGINFO flag of the sa_flags field is set and the implementation supports either the POSIX:RTS or the POSIX:XSI Extension, the sa_sigaction field specifies a signal-catching function. Example 8.14The following code segment sets the signal handler for SIGINT to mysighand.
In the POSIX base standard, a signal handler is an ordinary function that returns void and has one integer parameter. When the operating system delivers the signal, it sets this parameter to the number of the signal that was delivered. Most signal handlers ignore this value, but it is possible to have a single signal handler for many signals. The usefulness of signal handlers is limited by the inability to pass values to them. This capability has been added to the POSIX:RTS and POSIX:XSI Extensions, which can use the alternative sa_sigaction field of the struct sigaction structure to specify a handler. This section describes using the sa_handler field of sigaction to set up the handler; Section 9.4 describes using the sa_sigaction field for the handler.Two special values of the sa_handler member of struct sigaction are SIG_DFL> and SIG_IGN. The SIG_DFL value specifies that sigaction should restore the default action for the signal. The SIG_IGN value specifies that the process should handle the signal by ignoring it (throwing it away). Example 8.15The following code segment causes the process to ignore SIGINT if the default action is in effect for this signal.
Example 8.16The following code segment sets up a signal handler that catches the SIGINT signal generated by Ctrl-C.
Exercise 8.17Why didn't Table 8.2 on page 285 lists the functions that POSIX guarantees are async-signal safe. Example 8.18The following code segment sets the action of SIGINT to the default.
Example 8.19 testignored.cThe following function takes a signal number parameter and returns 1 if that signal is ignored and 0 otherwise.
Program 8.5 estimates the average value of sin(x) on the interval from 0 to 1 by computing the average of the sine of randomly picked values. The main program loop chooses a random value, x, between 0 and 1, adds sin(x) to a running sum, increments the count of the values, and prints the current count and average. The program illustrates the use of a signal handler to gracefully terminate a program. When the user enters Ctrl-C at standard input, the signal handler sets doneflag to signify that the program should terminate. On each iteration of the computation loop, the program tests doneflag to see whether it should drop out of the loop and print a final message. Program 8.5 signalterminate.cA program that terminates gracefully when it receives a Ctrl-C.
Code that accesses doneflag is a critical section because the signal handler can modify this variable while the main program examines it. (See Chapter 14 for a discussion of critical sections and atomic operations.) We handle the problem here by declaring doneflag to be sig_atomic_t, an integral type that is small enough to be accessed atomically. The volatile qualifier on doneflag informs the compiler that the variable may be changed asynchronously to program execution. Otherwise, the compiler might assume that doneflag is not modified in the while loop and generate code that only tests the condition on the first iteration of the loop. Exercise 8.20Why is it okay to use perror and printf in Program 8.5 even though these functions are not "signal safe"?Answer:Signal safety is a problem when both the signal handler and the main program use these functions. In this case, only the main program uses these functions.When both a signal handler and the main program need to access data that is larger than sig_atomic_t, care must be taken so that the data is not modified in one part of the program while being read in another. Program 8.6 also calculates the average value of sin(x) over the interval from 0 to 1, but it does not print the result on each iteration. Instead, the main program loop generates a string containing the results every 10,000th iteration. A signal handler for SIGUSR1 outputs the string when the user sends SIGUSR1 to the process. Program 8.6 averagesin.cA program to estimate the average values of sin(x) over the interval from 0 to 1.
The signal handler uses write instead of printf, since printf may not be safe to use in a signal handler. The handler avoids strlen for the same reason. The string and its length are global variables accessible to both the main program and the signal handler. Modifying the string in the main program and writing the string to standard output in the signal handler are critical sections for this program. The main program protects its critical section by having results block the signal while modifying the string and its length. Notice also that handler saves and restores errno, since write may change it.Legacy programs sometimes use signal instead of sigaction to specify signal handlers. Although signal is part of ISO C, it is unreliable even when used in a program with a single thread. Always use sigaction to set up your handlers. |