aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c18
-rw-r--r--kernel/signal.c27
2 files changed, 22 insertions, 23 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 8f3bf53a5b4d..2b332d170327 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -745,24 +745,6 @@ static void exit_notify(struct task_struct *tsk)
745 struct task_struct *t; 745 struct task_struct *t;
746 struct pid *pgrp; 746 struct pid *pgrp;
747 747
748 if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
749 && !thread_group_empty(tsk)) {
750 /*
751 * This occurs when there was a race between our exit
752 * syscall and a group signal choosing us as the one to
753 * wake up. It could be that we are the only thread
754 * alerted to check for pending signals, but another thread
755 * should be woken now to take the signal since we will not.
756 * Now we'll wake all the threads in the group just to make
757 * sure someone gets all the pending signals.
758 */
759 spin_lock_irq(&tsk->sighand->siglock);
760 for (t = next_thread(tsk); t != tsk; t = next_thread(t))
761 if (!signal_pending(t) && !(t->flags & PF_EXITING))
762 recalc_sigpending_and_wake(t);
763 spin_unlock_irq(&tsk->sighand->siglock);
764 }
765
766 /* 748 /*
767 * This does two things: 749 * This does two things:
768 * 750 *
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)) {