static void do_notify_parent_cldstop(struct task_struct *tsk, int why);
/*
- * Handle magic process-wide effects of stop/continue signals.
- * Unlike the signal actions, these happen immediately at signal-generation
+ * Handle magic process-wide effects of stop/continue signals. Unlike
+ * the signal actions, these happen immediately at signal-generation
* time regardless of blocking, ignoring, or handling. This does the
* actual continuing for SIGCONT, but not the actual stopping for stop
- * signals. The process stop is done as a signal action for SIG_DFL.
+ * signals. The process stop is done as a signal action for SIG_DFL.
+ *
+ * Returns true if the signal should be actually delivered, otherwise
+ * it should be dropped.
*/
-static void handle_stop_signal(int sig, struct task_struct *p)
+static int prepare_signal(int sig, struct task_struct *p)
{
struct signal_struct *signal = p->signal;
struct task_struct *t;
- if (signal->flags & SIGNAL_GROUP_EXIT)
+ if (unlikely(signal->flags & SIGNAL_GROUP_EXIT)) {
/*
- * The process is in the middle of dying already.
+ * The process is in the middle of dying, nothing to do.
*/
- return;
-
- if (sig_kernel_stop(sig)) {
+ } else if (sig_kernel_stop(sig)) {
/*
* This is a stop signal. Remove SIGCONT from all queues.
*/
signal->flags &= ~SIGNAL_STOP_DEQUEUED;
}
}
+
+ return !sig_ignored(p, sig);
}
/*
struct sigqueue *q;
assert_spin_locked(&t->sighand->siglock);
- handle_stop_signal(sig, t);
+ if (!prepare_signal(sig, t))
+ return 0;
pending = group ? &t->signal->shared_pending : &t->pending;
/*
* exactly one non-rt signal, so that we can get more
* detailed information about the cause of the signal.
*/
- if (sig_ignored(t, sig) || legacy_queue(pending, sig))
+ if (legacy_queue(pending, sig))
return 0;
/*
if (!likely(lock_task_sighand(t, &flags)))
goto ret;
- handle_stop_signal(sig, t);
-
- ret = 1;
- if (sig_ignored(t, sig))
+ ret = 1; /* the signal is ignored */
+ if (!prepare_signal(sig, t))
goto out;
ret = 0;