aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 5be0a406faeb..3e09b7cb3b20 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -810,8 +810,11 @@ static void ptrace_exit_finish(struct task_struct *parent,
810 } 810 }
811} 811}
812 812
813static void reparent_thread(struct task_struct *p, struct task_struct *father) 813/* Returns nonzero if the child should be released. */
814static int reparent_thread(struct task_struct *p, struct task_struct *father)
814{ 815{
816 int dead;
817
815 if (p->pdeath_signal) 818 if (p->pdeath_signal)
816 /* We already hold the tasklist_lock here. */ 819 /* We already hold the tasklist_lock here. */
817 group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p); 820 group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
@@ -819,12 +822,12 @@ static void reparent_thread(struct task_struct *p, struct task_struct *father)
819 list_move_tail(&p->sibling, &p->real_parent->children); 822 list_move_tail(&p->sibling, &p->real_parent->children);
820 823
821 if (task_detached(p)) 824 if (task_detached(p))
822 return; 825 return 0;
823 /* If this is a threaded reparent there is no need to 826 /* If this is a threaded reparent there is no need to
824 * notify anyone anything has happened. 827 * notify anyone anything has happened.
825 */ 828 */
826 if (same_thread_group(p->real_parent, father)) 829 if (same_thread_group(p->real_parent, father))
827 return; 830 return 0;
828 831
829 /* We don't want people slaying init. */ 832 /* We don't want people slaying init. */
830 p->exit_signal = SIGCHLD; 833 p->exit_signal = SIGCHLD;
@@ -832,11 +835,19 @@ static void reparent_thread(struct task_struct *p, struct task_struct *father)
832 /* If we'd notified the old parent about this child's death, 835 /* If we'd notified the old parent about this child's death,
833 * also notify the new parent. 836 * also notify the new parent.
834 */ 837 */
838 dead = 0;
835 if (!p->ptrace && 839 if (!p->ptrace &&
836 p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) 840 p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) {
837 do_notify_parent(p, p->exit_signal); 841 do_notify_parent(p, p->exit_signal);
842 if (task_detached(p)) {
843 p->exit_state = EXIT_DEAD;
844 dead = 1;
845 }
846 }
838 847
839 kill_orphaned_pgrp(p, father); 848 kill_orphaned_pgrp(p, father);
849
850 return dead;
840} 851}
841 852
842/* 853/*
@@ -896,7 +907,8 @@ static void forget_original_parent(struct task_struct *father)
896 BUG_ON(p->ptrace); 907 BUG_ON(p->ptrace);
897 p->parent = p->real_parent; 908 p->parent = p->real_parent;
898 } 909 }
899 reparent_thread(p, father); 910 if (reparent_thread(p, father))
911 list_add(&p->ptrace_entry, &ptrace_dead);;
900 } 912 }
901 913
902 write_unlock_irq(&tasklist_lock); 914 write_unlock_irq(&tasklist_lock);