aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 209eec11eef5..3d3adb94561d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1903,19 +1903,36 @@ relock:
1903void exit_signals(struct task_struct *tsk) 1903void exit_signals(struct task_struct *tsk)
1904{ 1904{
1905 int group_stop = 0; 1905 int group_stop = 0;
1906 struct task_struct *t;
1906 1907
1907 spin_lock_irq(&tsk->sighand->siglock); 1908 if (thread_group_empty(tsk) || signal_group_exit(tsk->signal)) {
1908 if (unlikely(tsk->signal->group_stop_count) && 1909 tsk->flags |= PF_EXITING;
1909 !--tsk->signal->group_stop_count) { 1910 return;
1910 tsk->signal->flags = SIGNAL_STOP_STOPPED;
1911 group_stop = 1;
1912 } 1911 }
1913 1912
1913 spin_lock_irq(&tsk->sighand->siglock);
1914 /* 1914 /*
1915 * From now this task is not visible for group-wide signals, 1915 * From now this task is not visible for group-wide signals,
1916 * see wants_signal(), do_signal_stop(). 1916 * see wants_signal(), do_signal_stop().
1917 */ 1917 */
1918 tsk->flags |= PF_EXITING; 1918 tsk->flags |= PF_EXITING;
1919 if (!signal_pending(tsk))
1920 goto out;
1921
1922 /* It could be that __group_complete_signal() choose us to
1923 * notify about group-wide signal. Another thread should be
1924 * woken now to take the signal since we will not.
1925 */
1926 for (t = tsk; (t = next_thread(t)) != tsk; )
1927 if (!signal_pending(t) && !(t->flags & PF_EXITING))
1928 recalc_sigpending_and_wake(t);
1929
1930 if (unlikely(tsk->signal->group_stop_count) &&
1931 !--tsk->signal->group_stop_count) {
1932 tsk->signal->flags = SIGNAL_STOP_STOPPED;
1933 group_stop = 1;
1934 }
1935out:
1919 spin_unlock_irq(&tsk->sighand->siglock); 1936 spin_unlock_irq(&tsk->sighand->siglock);
1920 1937
1921 if (unlikely(group_stop)) { 1938 if (unlikely(group_stop)) {