aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/fs/exec.c b/fs/exec.c
index ba73797eb4cb..10d493fea7ce 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -630,10 +630,9 @@ static inline int de_thread(struct task_struct *tsk)
630 /* 630 /*
631 * Account for the thread group leader hanging around: 631 * Account for the thread group leader hanging around:
632 */ 632 */
633 count = 2; 633 count = 1;
634 if (thread_group_leader(current)) 634 if (!thread_group_leader(current)) {
635 count = 1; 635 count = 2;
636 else {
637 /* 636 /*
638 * The SIGALRM timer survives the exec, but needs to point 637 * The SIGALRM timer survives the exec, but needs to point
639 * at us as the new group leader now. We have a race with 638 * at us as the new group leader now. We have a race with
@@ -642,8 +641,10 @@ static inline int de_thread(struct task_struct *tsk)
642 * before we can safely let the old group leader die. 641 * before we can safely let the old group leader die.
643 */ 642 */
644 sig->real_timer.data = (unsigned long)current; 643 sig->real_timer.data = (unsigned long)current;
644 spin_unlock_irq(lock);
645 if (del_timer_sync(&sig->real_timer)) 645 if (del_timer_sync(&sig->real_timer))
646 add_timer(&sig->real_timer); 646 add_timer(&sig->real_timer);
647 spin_lock_irq(lock);
647 } 648 }
648 while (atomic_read(&sig->count) > count) { 649 while (atomic_read(&sig->count) > count) {
649 sig->group_exit_task = current; 650 sig->group_exit_task = current;
@@ -655,7 +656,6 @@ static inline int de_thread(struct task_struct *tsk)
655 } 656 }
656 sig->group_exit_task = NULL; 657 sig->group_exit_task = NULL;
657 sig->notify_count = 0; 658 sig->notify_count = 0;
658 sig->real_timer.data = (unsigned long)current;
659 spin_unlock_irq(lock); 659 spin_unlock_irq(lock);
660 660
661 /* 661 /*
@@ -1417,19 +1417,16 @@ static void zap_threads (struct mm_struct *mm)
1417static void coredump_wait(struct mm_struct *mm) 1417static void coredump_wait(struct mm_struct *mm)
1418{ 1418{
1419 DECLARE_COMPLETION(startup_done); 1419 DECLARE_COMPLETION(startup_done);
1420 int core_waiters;
1420 1421
1421 mm->core_waiters++; /* let other threads block */
1422 mm->core_startup_done = &startup_done; 1422 mm->core_startup_done = &startup_done;
1423 1423
1424 /* give other threads a chance to run: */
1425 yield();
1426
1427 zap_threads(mm); 1424 zap_threads(mm);
1428 if (--mm->core_waiters) { 1425 core_waiters = mm->core_waiters;
1429 up_write(&mm->mmap_sem); 1426 up_write(&mm->mmap_sem);
1427
1428 if (core_waiters)
1430 wait_for_completion(&startup_done); 1429 wait_for_completion(&startup_done);
1431 } else
1432 up_write(&mm->mmap_sem);
1433 BUG_ON(mm->core_waiters); 1430 BUG_ON(mm->core_waiters);
1434} 1431}
1435 1432
@@ -1463,11 +1460,21 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
1463 current->fsuid = 0; /* Dump root private */ 1460 current->fsuid = 0; /* Dump root private */
1464 } 1461 }
1465 mm->dumpable = 0; 1462 mm->dumpable = 0;
1466 init_completion(&mm->core_done); 1463
1464 retval = -EAGAIN;
1467 spin_lock_irq(&current->sighand->siglock); 1465 spin_lock_irq(&current->sighand->siglock);
1468 current->signal->flags = SIGNAL_GROUP_EXIT; 1466 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
1469 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 }
1470 spin_unlock_irq(&current->sighand->siglock); 1471 spin_unlock_irq(&current->sighand->siglock);
1472 if (retval) {
1473 up_write(&mm->mmap_sem);
1474 goto fail;
1475 }
1476
1477 init_completion(&mm->core_done);
1471 coredump_wait(mm); 1478 coredump_wait(mm);
1472 1479
1473 /* 1480 /*