diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 39 |
1 files changed, 23 insertions, 16 deletions
@@ -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) | |||
1417 | static void coredump_wait(struct mm_struct *mm) | 1417 | static 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(¤t->sighand->siglock); | 1465 | spin_lock_irq(¤t->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(¤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); | ||
1471 | coredump_wait(mm); | 1478 | coredump_wait(mm); |
1472 | 1479 | ||
1473 | /* | 1480 | /* |