[ Team LiB ] |
8.3 Manipulating Signal Masks and Signal SetsA process can temporarily prevent a signal from being delivered by blocking it. Blocked signals do not affect the behavior of the process until they are delivered. The process signal mask gives the set of signals that are currently blocked. The signal mask is of type sigset_t. Blocking a signal is different from ignoring a signal. When a process blocks a signal, the operating system does not deliver the signal until the process unblocks the signal. A process blocks a signal by modifying its signal mask with sigprocmask. When a process ignores a signal, the signal is delivered and the process handles it by throwing it away. The process sets a signal to be ignored by calling sigaction with a handler of SIG_IGN, as described in Section 8.4. Specify operations (such as blocking or unblocking) on groups of signals by using signal sets of type sigset_t. Signal sets are manipulated by the five functions listed in the following synopsis box. The first parameter for each function is a pointer to a sigset_t. The sigaddset adds signo to the signal set, and the sigdelset removes signo from the signal set. The sigemptyset function initializes a sigset_t to contain no signals; sigfillset initializes a sigset_t to contain all signals. Initialize a signal set by calling either sigemptyset or sigfillset before using it. The sigismember reports whether signo is in a sigset_t.
The sigismember function returns 1 if signo is in *set and 0 if signo is not in *set. If successful, the other functions return 0. If unsuccessful, these other functions return �1 and set errno. POSIX does not define any mandatory errors for these functions. Example 8.9The following code segment initializes signal set twosigs to contain exactly the two signals SIGINT and SIGQUIT.
A process can examine or modify its process signal mask with the sigprocmask function. The how parameter is an integer specifying the manner in which the signal mask is to be modified. The set parameter is a pointer to a signal set to be used in the modification. If set is NULL, no modification is made. If oset is not NULL, the sigprocmask returns in *oset the signal set before the modification.
If successful, sigprocmask returns 0. If unsuccessful, sigprocmask returns �1 and sets errno. The sigprocmask function sets errno to EINVAL if how is invalid. The sigprocmask function should only be used by a process with a single thread. When multiple threads exist, the pthread_sigmask function (page 474) should be used. The how parameter, which specifies the manner in which the signal mask is to be modified, can take on one of the following three values.
Keep in mind that some signals, such as SIGSTOP and SIGKILL, cannot be blocked. If an attempt is made to block these signals, the system ignores the request without reporting an error. Example 8.10The following code segment adds SIGINT to the set of signals that the process has blocked.
If SIGINT is already blocked, the call to sigprocmask has no effect. Program 8.1 displays a message, blocks the SIGINT signal while doing some useless work, unblocks the signal, and does more useless work. The program repeats this sequence continually in a loop. If a user enters Ctrl-C while SIGINT is blocked, Program 8.1 finishes the calculation and prints a message before terminating. If a user types Ctrl-C while SIGINT is unblocked, the program terminates immediately. Program 8.1 blocktest.cA program that blocks and unblocks SIGINT.
The function makepair of Program 8.2 takes two pathnames as parameters and creates two named pipes with these names. If successful, makepair returns 0. If unsuccessful, makepair returns �1 and sets errno. The function blocks all signals during the creation of the two pipes to be sure that it can deallocate both pipes if there is an error. The function restores the original signal mask before the return. The if statement relies on the conditional left-to-right evaluation of && and ||. Exercise 8.11Is it possible that after a call to makepair, pipe1 exists but pipe2 does not? Answer: Yes. This could happen if pipe1 already exists but pipe2 does not and the user does not have write permission to the directory. It could also happen if the SIGKILL signal is delivered between the two calls to mkfifo. Program 8.2 makepair.cA function that blocks signals while creating two pipes. (See Exercise 8.11 and Exercise 8.12 for a discussion of some flaws.)
Exercise 8.12Does a makepair return value of 0 guarantee that FIFOs corresponding to pipe1 and pipe2 are available on return? Answer: If one of the files already exists, mkfifo returns �1 and sets errno to EEXIST. The makepair function assumes that the FIFO exists without checking whether the file was a FIFO or an ordinary file. Thus, it is possible for makepair to indicate success even if this previously existing file is not a FIFO. In Program 8.3, the parent blocks all signals before forking a child process to execute an ls command. Processes inherit the signal mask after both fork and exec, so the ls command executes with signals blocked. The child created by fork in Program 8.3 has a copy of the original signal mask saved in oldmask. An exec command overwrites all program variables, so an executed process cannot restore the original mask once exec takes place. The parent restores the original signal mask and then waits for the child. Program 8.3 blockchild.cA program that blocks signals before calling fork and execl.
Exercise 8.13Run Program 8.3 from a working directory with a large number of files. Experiment with entering Ctrl-C at various points during the execution and explain what happens. Answer: The main program can be interrupted while the listing is being displayed, and the prompt will appear in the middle of the listing. The execution of ls will not be interrupted by the signal. Program 8.4 password.cA function that retrieves a user password.
Program 8.4 shows an improvement on the passwordnosigs function of Program 6.13 on page 208. The password function blocks SIGINT, SIGQUIT and SIGTSTP while terminal echo is set off, preventing the terminal from being placed in an unusable state if one of these signals is delivered to the process while this function is executing. |
[ Team LiB ] |
No comments:
Post a Comment