diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 063745699f7f..8061891ddd9b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -560,19 +560,26 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p, | |||
560 | kill_orphaned_pgrp(p, father); | 560 | kill_orphaned_pgrp(p, father); |
561 | } | 561 | } |
562 | 562 | ||
563 | static void forget_original_parent(struct task_struct *father) | 563 | /* |
564 | * This does two things: | ||
565 | * | ||
566 | * A. Make init inherit all the child processes | ||
567 | * B. Check to see if any process groups have become orphaned | ||
568 | * as a result of our exiting, and if they have any stopped | ||
569 | * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) | ||
570 | */ | ||
571 | static void forget_original_parent(struct task_struct *father, | ||
572 | struct list_head *dead) | ||
564 | { | 573 | { |
565 | struct task_struct *p, *t, *n, *reaper; | 574 | struct task_struct *p, *t, *reaper; |
566 | LIST_HEAD(dead_children); | ||
567 | 575 | ||
568 | write_lock_irq(&tasklist_lock); | ||
569 | if (unlikely(!list_empty(&father->ptraced))) | 576 | if (unlikely(!list_empty(&father->ptraced))) |
570 | exit_ptrace(father, &dead_children); | 577 | exit_ptrace(father, dead); |
571 | 578 | ||
572 | /* Can drop and reacquire tasklist_lock */ | 579 | /* Can drop and reacquire tasklist_lock */ |
573 | reaper = find_child_reaper(father); | 580 | reaper = find_child_reaper(father); |
574 | if (list_empty(&father->children)) | 581 | if (list_empty(&father->children)) |
575 | goto unlock; | 582 | return; |
576 | 583 | ||
577 | reaper = find_new_reaper(father, reaper); | 584 | reaper = find_new_reaper(father, reaper); |
578 | list_for_each_entry(p, &father->children, sibling) { | 585 | list_for_each_entry(p, &father->children, sibling) { |
@@ -590,16 +597,9 @@ static void forget_original_parent(struct task_struct *father) | |||
590 | * notify anyone anything has happened. | 597 | * notify anyone anything has happened. |
591 | */ | 598 | */ |
592 | if (!same_thread_group(reaper, father)) | 599 | if (!same_thread_group(reaper, father)) |
593 | reparent_leader(father, p, &dead_children); | 600 | reparent_leader(father, p, dead); |
594 | } | 601 | } |
595 | list_splice_tail_init(&father->children, &reaper->children); | 602 | list_splice_tail_init(&father->children, &reaper->children); |
596 | unlock: | ||
597 | write_unlock_irq(&tasklist_lock); | ||
598 | |||
599 | list_for_each_entry_safe(p, n, &dead_children, ptrace_entry) { | ||
600 | list_del_init(&p->ptrace_entry); | ||
601 | release_task(p); | ||
602 | } | ||
603 | } | 603 | } |
604 | 604 | ||
605 | /* | 605 | /* |
@@ -609,18 +609,12 @@ static void forget_original_parent(struct task_struct *father) | |||
609 | static void exit_notify(struct task_struct *tsk, int group_dead) | 609 | static void exit_notify(struct task_struct *tsk, int group_dead) |
610 | { | 610 | { |
611 | bool autoreap; | 611 | bool autoreap; |
612 | 612 | struct task_struct *p, *n; | |
613 | /* | 613 | LIST_HEAD(dead); |
614 | * This does two things: | ||
615 | * | ||
616 | * A. Make init inherit all the child processes | ||
617 | * B. Check to see if any process groups have become orphaned | ||
618 | * as a result of our exiting, and if they have any stopped | ||
619 | * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) | ||
620 | */ | ||
621 | forget_original_parent(tsk); | ||
622 | 614 | ||
623 | write_lock_irq(&tasklist_lock); | 615 | write_lock_irq(&tasklist_lock); |
616 | forget_original_parent(tsk, &dead); | ||
617 | |||
624 | if (group_dead) | 618 | if (group_dead) |
625 | kill_orphaned_pgrp(tsk->group_leader, NULL); | 619 | kill_orphaned_pgrp(tsk->group_leader, NULL); |
626 | 620 | ||
@@ -644,6 +638,11 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
644 | wake_up_process(tsk->signal->group_exit_task); | 638 | wake_up_process(tsk->signal->group_exit_task); |
645 | write_unlock_irq(&tasklist_lock); | 639 | write_unlock_irq(&tasklist_lock); |
646 | 640 | ||
641 | list_for_each_entry_safe(p, n, &dead, ptrace_entry) { | ||
642 | list_del_init(&p->ptrace_entry); | ||
643 | release_task(p); | ||
644 | } | ||
645 | |||
647 | /* If the process is dead, release it - nobody will wait for it */ | 646 | /* If the process is dead, release it - nobody will wait for it */ |
648 | if (autoreap) | 647 | if (autoreap) |
649 | release_task(tsk); | 648 | release_task(tsk); |