diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2005-10-30 18:02:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 20:37:19 -0500 |
commit | 932aeafbe8521a9a9d790152d66020e0fef2029b (patch) | |
tree | 09b95edbd9c160962027a9b3dcbf3cb7fc7a2b90 | |
parent | 2f51201662b28dbf8c15fb7eb972bc51c6cc3fa5 (diff) |
[PATCH] fix de_thread vs it_real_fn() deadlock
de_thread() calls del_timer_sync(->real_timer) under ->sighand->siglock.
This is deadlockable, it_real_fn sends a signal and needs this lock too.
Also, delete unneeded ->real_timer.data assignment.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/exec.c | 3 |
1 files changed, 2 insertions, 1 deletions
@@ -641,8 +641,10 @@ static inline int de_thread(struct task_struct *tsk) | |||
641 | * before we can safely let the old group leader die. | 641 | * before we can safely let the old group leader die. |
642 | */ | 642 | */ |
643 | sig->real_timer.data = (unsigned long)current; | 643 | sig->real_timer.data = (unsigned long)current; |
644 | spin_unlock_irq(lock); | ||
644 | if (del_timer_sync(&sig->real_timer)) | 645 | if (del_timer_sync(&sig->real_timer)) |
645 | add_timer(&sig->real_timer); | 646 | add_timer(&sig->real_timer); |
647 | spin_lock_irq(lock); | ||
646 | } | 648 | } |
647 | while (atomic_read(&sig->count) > count) { | 649 | while (atomic_read(&sig->count) > count) { |
648 | sig->group_exit_task = current; | 650 | sig->group_exit_task = current; |
@@ -654,7 +656,6 @@ static inline int de_thread(struct task_struct *tsk) | |||
654 | } | 656 | } |
655 | sig->group_exit_task = NULL; | 657 | sig->group_exit_task = NULL; |
656 | sig->notify_count = 0; | 658 | sig->notify_count = 0; |
657 | sig->real_timer.data = (unsigned long)current; | ||
658 | spin_unlock_irq(lock); | 659 | spin_unlock_irq(lock); |
659 | 660 | ||
660 | /* | 661 | /* |