diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 464971e6923e..772e9175735c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -529,15 +529,7 @@ static struct task_struct *find_new_reaper(struct task_struct *father) | |||
529 | static void reparent_leader(struct task_struct *father, struct task_struct *p, | 529 | static void reparent_leader(struct task_struct *father, struct task_struct *p, |
530 | struct list_head *dead) | 530 | struct list_head *dead) |
531 | { | 531 | { |
532 | list_move_tail(&p->sibling, &p->real_parent->children); | 532 | if (unlikely(p->exit_state == EXIT_DEAD)) |
533 | |||
534 | if (p->exit_state == EXIT_DEAD) | ||
535 | return; | ||
536 | /* | ||
537 | * If this is a threaded reparent there is no need to | ||
538 | * notify anyone anything has happened. | ||
539 | */ | ||
540 | if (same_thread_group(p->real_parent, father)) | ||
541 | return; | 533 | return; |
542 | 534 | ||
543 | /* We don't want people slaying init. */ | 535 | /* We don't want people slaying init. */ |
@@ -568,7 +560,7 @@ static void forget_original_parent(struct task_struct *father) | |||
568 | exit_ptrace(father); | 560 | exit_ptrace(father); |
569 | reaper = find_new_reaper(father); | 561 | reaper = find_new_reaper(father); |
570 | 562 | ||
571 | list_for_each_entry_safe(p, n, &father->children, sibling) { | 563 | list_for_each_entry(p, &father->children, sibling) { |
572 | for_each_thread(p, t) { | 564 | for_each_thread(p, t) { |
573 | t->real_parent = reaper; | 565 | t->real_parent = reaper; |
574 | BUG_ON((!t->ptrace) != (t->parent == father)); | 566 | BUG_ON((!t->ptrace) != (t->parent == father)); |
@@ -578,12 +570,16 @@ static void forget_original_parent(struct task_struct *father) | |||
578 | group_send_sig_info(t->pdeath_signal, | 570 | group_send_sig_info(t->pdeath_signal, |
579 | SEND_SIG_NOINFO, t); | 571 | SEND_SIG_NOINFO, t); |
580 | } | 572 | } |
581 | reparent_leader(father, p, &dead_children); | 573 | /* |
574 | * If this is a threaded reparent there is no need to | ||
575 | * notify anyone anything has happened. | ||
576 | */ | ||
577 | if (!same_thread_group(reaper, father)) | ||
578 | reparent_leader(father, p, &dead_children); | ||
582 | } | 579 | } |
580 | list_splice_tail_init(&father->children, &reaper->children); | ||
583 | write_unlock_irq(&tasklist_lock); | 581 | write_unlock_irq(&tasklist_lock); |
584 | 582 | ||
585 | BUG_ON(!list_empty(&father->children)); | ||
586 | |||
587 | list_for_each_entry_safe(p, n, &dead_children, ptrace_entry) { | 583 | list_for_each_entry_safe(p, n, &dead_children, ptrace_entry) { |
588 | list_del_init(&p->ptrace_entry); | 584 | list_del_init(&p->ptrace_entry); |
589 | release_task(p); | 585 | release_task(p); |