diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2005-10-30 18:02:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 20:37:25 -0500 |
commit | 1291cf4163d21f1b4999d697cbf68d38e7151c28 (patch) | |
tree | 0e1c3e3970216c769f91f6077b0e23d47d6fd333 | |
parent | f7232056bff5fe2d3bfeab35252a66ebaeb5bbde (diff) |
[PATCH] fix de_thread() vs do_coredump() deadlock
de_thread() sends SIGKILL to all sub-threads and waits them to die in 'D'
state. It is possible that one of the threads already dequeued coredump
signal. When de_thread() unlocks ->sighand->lock that thread can enter
do_coredump()->coredump_wait() and cause a deadlock.
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 | 16 |
1 files changed, 13 insertions, 3 deletions
@@ -1460,11 +1460,21 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1460 | current->fsuid = 0; /* Dump root private */ | 1460 | current->fsuid = 0; /* Dump root private */ |
1461 | } | 1461 | } |
1462 | mm->dumpable = 0; | 1462 | mm->dumpable = 0; |
1463 | init_completion(&mm->core_done); | 1463 | |
1464 | retval = -EAGAIN; | ||
1464 | spin_lock_irq(¤t->sighand->siglock); | 1465 | spin_lock_irq(¤t->sighand->siglock); |
1465 | current->signal->flags = SIGNAL_GROUP_EXIT; | 1466 | if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { |
1466 | current->signal->group_exit_code = exit_code; | 1467 | current->signal->flags = SIGNAL_GROUP_EXIT; |
1468 | current->signal->group_exit_code = exit_code; | ||
1469 | retval = 0; | ||
1470 | } | ||
1467 | spin_unlock_irq(¤t->sighand->siglock); | 1471 | spin_unlock_irq(¤t->sighand->siglock); |
1472 | if (retval) { | ||
1473 | up_write(&mm->mmap_sem); | ||
1474 | goto fail; | ||
1475 | } | ||
1476 | |||
1477 | init_completion(&mm->core_done); | ||
1468 | coredump_wait(mm); | 1478 | coredump_wait(mm); |
1469 | 1479 | ||
1470 | /* | 1480 | /* |