aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 9b6fda5e87f1..e20724af9b36 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -625,6 +625,33 @@ void signal_wake_up(struct task_struct *t, int resume)
625 * Returns 1 if any signals were found. 625 * Returns 1 if any signals were found.
626 * 626 *
627 * All callers must be holding the siglock. 627 * All callers must be holding the siglock.
628 *
629 * This version takes a sigset mask and looks at all signals,
630 * not just those in the first mask word.
631 */
632static int rm_from_queue_full(sigset_t *mask, struct sigpending *s)
633{
634 struct sigqueue *q, *n;
635 sigset_t m;
636
637 sigandsets(&m, mask, &s->signal);
638 if (sigisemptyset(&m))
639 return 0;
640
641 signandsets(&s->signal, &s->signal, mask);
642 list_for_each_entry_safe(q, n, &s->list, list) {
643 if (sigismember(mask, q->info.si_signo)) {
644 list_del_init(&q->list);
645 __sigqueue_free(q);
646 }
647 }
648 return 1;
649}
650/*
651 * Remove signals in mask from the pending set and queue.
652 * Returns 1 if any signals were found.
653 *
654 * All callers must be holding the siglock.
628 */ 655 */
629static int rm_from_queue(unsigned long mask, struct sigpending *s) 656static int rm_from_queue(unsigned long mask, struct sigpending *s)
630{ 657{
@@ -2408,6 +2435,7 @@ int
2408do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) 2435do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
2409{ 2436{
2410 struct k_sigaction *k; 2437 struct k_sigaction *k;
2438 sigset_t mask;
2411 2439
2412 if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig))) 2440 if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
2413 return -EINVAL; 2441 return -EINVAL;
@@ -2455,9 +2483,11 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
2455 *k = *act; 2483 *k = *act;
2456 sigdelsetmask(&k->sa.sa_mask, 2484 sigdelsetmask(&k->sa.sa_mask,
2457 sigmask(SIGKILL) | sigmask(SIGSTOP)); 2485 sigmask(SIGKILL) | sigmask(SIGSTOP));
2458 rm_from_queue(sigmask(sig), &t->signal->shared_pending); 2486 sigemptyset(&mask);
2487 sigaddset(&mask, sig);
2488 rm_from_queue_full(&mask, &t->signal->shared_pending);
2459 do { 2489 do {
2460 rm_from_queue(sigmask(sig), &t->pending); 2490 rm_from_queue_full(&mask, &t->pending);
2461 recalc_sigpending_tsk(t); 2491 recalc_sigpending_tsk(t);
2462 t = next_thread(t); 2492 t = next_thread(t);
2463 } while (t != current); 2493 } while (t != current);