aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Nyberg <alexn@telia.com>2005-09-14 12:54:06 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-14 13:26:34 -0400
commitfb085cf1d4294824571815d487daccc0609543f0 (patch)
treee3a704026e65bf6fea0c7747f0fb75a506f54127
parent32a3658533c6f4c6bf370dd730213e802464ef9b (diff)
[PATCH] Fix fs/exec.c:788 (de_thread()) BUG_ON
It turns out that the BUG_ON() in fs/exec.c: de_thread() is unreliable and can trigger due to the test itself being racy. de_thread() does while (atomic_read(&sig->count) > count) { } ..... ..... BUG_ON(!thread_group_empty(current)); but release_task does write_lock_irq(&tasklist_lock) __exit_signal (this is where atomic_dec(&sig->count) is run) __exit_sighand __unhash_process takes write lock on tasklist_lock remove itself out of PIDTYPE_TGID list write_unlock_irq(&tasklist_lock) so there's a clear (although small) window between the atomic_dec(&sig->count) and the actual PIDTYPE_TGID unhashing of the thread. And actually there is no need for all threads to have exited at this point, so we simply kill the BUG_ON. Big thanks to Marc Lehmann who provided the test-case. Fixes Bug 5170 (http://bugme.osdl.org/show_bug.cgi?id=5170) Signed-off-by: Alexander Nyberg <alexn@telia.com> Cc: Roland McGrath <roland@redhat.com> Cc: Andrew Morton <akpm@osdl.org> Cc: Ingo Molnar <mingo@elte.hu> Acked-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/exec.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 14dd03907ccb..6fae59a22b43 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -745,8 +745,8 @@ static inline int de_thread(struct task_struct *tsk)
745 } 745 }
746 746
747 /* 747 /*
748 * Now there are really no other threads at all, 748 * There may be one thread left which is just exiting,
749 * so it's safe to stop telling them to kill themselves. 749 * but it's safe to stop telling the group to kill themselves.
750 */ 750 */
751 sig->flags = 0; 751 sig->flags = 0;
752 752
@@ -785,7 +785,6 @@ no_thread_group:
785 kmem_cache_free(sighand_cachep, oldsighand); 785 kmem_cache_free(sighand_cachep, oldsighand);
786 } 786 }
787 787
788 BUG_ON(!thread_group_empty(current));
789 BUG_ON(!thread_group_leader(current)); 788 BUG_ON(!thread_group_leader(current));
790 return 0; 789 return 0;
791} 790}