diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/exit.c | 18 | ||||
-rw-r--r-- | kernel/signal.c | 27 |
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: | |||
1903 | void exit_signals(struct task_struct *tsk) | 1903 | void 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 | } | ||
1935 | out: | ||
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)) { |