diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 0db1d93c4d68..359c4de7c772 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -558,24 +558,25 @@ static int check_kill_permission(int sig, struct siginfo *info, | |||
558 | static void do_notify_parent_cldstop(struct task_struct *tsk, int why); | 558 | static void do_notify_parent_cldstop(struct task_struct *tsk, int why); |
559 | 559 | ||
560 | /* | 560 | /* |
561 | * Handle magic process-wide effects of stop/continue signals. | 561 | * Handle magic process-wide effects of stop/continue signals. Unlike |
562 | * Unlike the signal actions, these happen immediately at signal-generation | 562 | * the signal actions, these happen immediately at signal-generation |
563 | * time regardless of blocking, ignoring, or handling. This does the | 563 | * time regardless of blocking, ignoring, or handling. This does the |
564 | * actual continuing for SIGCONT, but not the actual stopping for stop | 564 | * actual continuing for SIGCONT, but not the actual stopping for stop |
565 | * signals. The process stop is done as a signal action for SIG_DFL. | 565 | * signals. The process stop is done as a signal action for SIG_DFL. |
566 | * | ||
567 | * Returns true if the signal should be actually delivered, otherwise | ||
568 | * it should be dropped. | ||
566 | */ | 569 | */ |
567 | static void handle_stop_signal(int sig, struct task_struct *p) | 570 | static int prepare_signal(int sig, struct task_struct *p) |
568 | { | 571 | { |
569 | struct signal_struct *signal = p->signal; | 572 | struct signal_struct *signal = p->signal; |
570 | struct task_struct *t; | 573 | struct task_struct *t; |
571 | 574 | ||
572 | if (signal->flags & SIGNAL_GROUP_EXIT) | 575 | if (unlikely(signal->flags & SIGNAL_GROUP_EXIT)) { |
573 | /* | 576 | /* |
574 | * The process is in the middle of dying already. | 577 | * The process is in the middle of dying, nothing to do. |
575 | */ | 578 | */ |
576 | return; | 579 | } else if (sig_kernel_stop(sig)) { |
577 | |||
578 | if (sig_kernel_stop(sig)) { | ||
579 | /* | 580 | /* |
580 | * This is a stop signal. Remove SIGCONT from all queues. | 581 | * This is a stop signal. Remove SIGCONT from all queues. |
581 | */ | 582 | */ |
@@ -644,6 +645,8 @@ static void handle_stop_signal(int sig, struct task_struct *p) | |||
644 | signal->flags &= ~SIGNAL_STOP_DEQUEUED; | 645 | signal->flags &= ~SIGNAL_STOP_DEQUEUED; |
645 | } | 646 | } |
646 | } | 647 | } |
648 | |||
649 | return !sig_ignored(p, sig); | ||
647 | } | 650 | } |
648 | 651 | ||
649 | /* | 652 | /* |
@@ -753,7 +756,8 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
753 | struct sigqueue *q; | 756 | struct sigqueue *q; |
754 | 757 | ||
755 | assert_spin_locked(&t->sighand->siglock); | 758 | assert_spin_locked(&t->sighand->siglock); |
756 | handle_stop_signal(sig, t); | 759 | if (!prepare_signal(sig, t)) |
760 | return 0; | ||
757 | 761 | ||
758 | pending = group ? &t->signal->shared_pending : &t->pending; | 762 | pending = group ? &t->signal->shared_pending : &t->pending; |
759 | /* | 763 | /* |
@@ -761,7 +765,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
761 | * exactly one non-rt signal, so that we can get more | 765 | * exactly one non-rt signal, so that we can get more |
762 | * detailed information about the cause of the signal. | 766 | * detailed information about the cause of the signal. |
763 | */ | 767 | */ |
764 | if (sig_ignored(t, sig) || legacy_queue(pending, sig)) | 768 | if (legacy_queue(pending, sig)) |
765 | return 0; | 769 | return 0; |
766 | 770 | ||
767 | /* | 771 | /* |
@@ -1247,10 +1251,8 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) | |||
1247 | if (!likely(lock_task_sighand(t, &flags))) | 1251 | if (!likely(lock_task_sighand(t, &flags))) |
1248 | goto ret; | 1252 | goto ret; |
1249 | 1253 | ||
1250 | handle_stop_signal(sig, t); | 1254 | ret = 1; /* the signal is ignored */ |
1251 | 1255 | if (!prepare_signal(sig, t)) | |
1252 | ret = 1; | ||
1253 | if (sig_ignored(t, sig)) | ||
1254 | goto out; | 1256 | goto out; |
1255 | 1257 | ||
1256 | ret = 0; | 1258 | ret = 0; |