int do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) { struct k_sigaction *k;
if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig))) return -EINVAL;
k = ¤tt->sighand->action[sig-1];
spin_lock_irq(¤tt->sighand->siglock); if (signal_pending(current)) { /* * If there might be a fatal signal pending on multiple * threads, make sure we take it before changing the action. */ spin_unlock_irq(¤tt->sighand->siglock); return -ERESTARTNOINTR; }
if (oact)//把原来的k_sigaction保存到oact结构中,这里是对整个数据结构进行复制 *oact = *k;
if (act) { /* * POSIX 3.3.1.3: * "Setting a signal action to SIG_IGN for a signal that is * pending shall cause the pending signal to be discarded, * whether or not it is blocked." * * "Setting a signal action to SIG_DFL for a signal that is * pending and whose default action is to ignore the signal * (for example, SIGCHLD), shall cause the pending signal to * be discarded, whether or not it is blocked" */ if (act->sa.sa_handler == SIG_IGN || (act->sa.sa_handler == SIG_DFL && sig_kernel_ignore(sig))) { /* * This is a fairly rare case, so we only take the * tasklist_lock once we're sure we'll need it. * Now we must do this little unlock and relock * dance to maintain the lock hierarchy. */ struct task_struct *t = current; spin_unlock_irq(&t->sighand->siglock); read_lock(&tasklist_lock); spin_lock_irq(&t->sighand->siglock); *k = *act; //把新的k_sigaction结构复制到进程的sighand->action中
sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP)); rm_from_queue(sigmask(sig), &t->signal->shared_pending); do { rm_from_queue(sigmask(sig), &t->pending); recalc_sigpending_tsk(t); t = next_thread(t); } while (t != current); spin_unlock_irq(¤t->sighand->siglock); read_unlock(&tasklist_lock); return 0; }
*k = *act; //把新的k_sigaction结构复制到进程的sighand->action中 sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP)); }
spin_unlock_irq(¤tt->sighand->siglock); return 0; } |