Changing a Signal Action

The sigaction(sig,act,oact) system call allows users to specify an action for a signal; of course, if no signal action is defined, the kernel executes the default action associated with the delivered signal.

The corresponding sys_sigaction( ) service routine acts on two parameters: the sig signal number and the act table of type sigaction that specifies the new action. A third oact optional output parameter may be used to get the previous action associated with the signal.

The function checks first whether the act address is valid. Then it fills the sa_handler, sa_flags, and sa_mask fields of a new_ka local variable of type k_sigaction with the corresponding fields of *act:

get user(new ka.sa.sa handler, &act->sa handler); get user(new ka.sa.sa flags, &act->sa flags); get user(mask, &act->sa mask); siginitset(&new ka.sa.sa mask, mask);

The function invokes do_sigaction( ) to copy the new new_ka table into the entry at the sig-1 position of current->sig->action (the number of the signal is one higher than the position in the array because there is no zero signal):

k = &current->sig->action[sig-1]; spin lock(&current->sig->siglock); if (act) {

sigdelsetmask(&k->sa.sa mask, sigmask(SIGKILL) | sigmask(SIGSTOP)); if (k->sa.sa_handler == SIG_IGN || (k->sa.sa_handler == SIG_DFL &&

(sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH))) { spin lock irq(&current->sigmask lock); if (rm sig from queue(sig, current))

recalc sigpending(current); spin unlock irq(&current->sigmask lock);

The POSIX standard requires that setting a signal action to either SIG_IGN or sig_dfl when the default action is "ignore," causes any pending signal of the same type to be discarded. Moreover, notice that no matter what the requested masked signals are for the signal handler, sigkill and sigstop are never masked.

If the oact parameter is not null, the contents of the previous sigaction table are copied to the process address space at the address specified by that parameter:

put user(old ka.sa.sa handler, &oact->sa handler);

put user(old ka.sa.sa flags, &oact->sa flags);

put user(old ka.sa.sa mask.sig[0], &oact->sa mask);

Notice that the sigaction( ) system call also allows initialization of the sa_flags field in the sigaction table. We listed the values allowed for this field and the related meanings in Table 10-4 (earlier in this chapter).

Older System V Unix variants offered the signal( ) system call, which is still widely used by programmers. Recent C libraries implement signal( ) by means of sigaction( ). However, Linux still supports older C libraries and offers the sys_signal( ) service routine:

new sa.sa.sa handler = handler;

new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;

return ret ? ret : (unsigned long)old sa.sa.sa handler;

Continue reading here: Examining the Pending Blocked Signals

Was this article helpful?

0 0