aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/signal.c32
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,
558static void do_notify_parent_cldstop(struct task_struct *tsk, int why); 558static 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 */
567static void handle_stop_signal(int sig, struct task_struct *p) 570static 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;