aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-12-21 23:28:40 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-22 12:03:41 -0500
commitb2b2cbc4b2a2f389442549399a993a8306420baf (patch)
treef734441636bbeba1c07aeeb84a05e0deac7b8d64
parentef129412b4cbd6686d0749612cb9b76e207271f4 (diff)
[PATCH] Fix reparenting to the same thread group. (take 2)
This patch fixes the case when we reparent to a different thread in the same thread group. This modifies the code so that we do not send signals and do not change the signal to send to SIGCHLD unless we have change the thread group of our parents. It also suppresses sending pdeath_sig in this cas as well since the result of geppid doesn't change. Thanks to Oleg for spotting my bug of only fixing this for non-ptraced tasks. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Albert Cahalan <acahalan@gmail.com> Cc: Andrew Morton <akpm@osdl.org> Cc: Roland McGrath <roland@redhat.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Coywolf Qi Hunt <qiyong@fc-cn.com> Acked-by: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--kernel/exit.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 85917c2bf065..46cf6b681460 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -597,14 +597,6 @@ choose_new_parent(struct task_struct *p, struct task_struct *reaper)
597static void 597static void
598reparent_thread(struct task_struct *p, struct task_struct *father, int traced) 598reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
599{ 599{
600 /* We don't want people slaying init. */
601 if (p->exit_signal != -1)
602 p->exit_signal = SIGCHLD;
603
604 if (p->pdeath_signal)
605 /* We already hold the tasklist_lock here. */
606 group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
607
608 /* Move the child from its dying parent to the new one. */ 600 /* Move the child from its dying parent to the new one. */
609 if (unlikely(traced)) { 601 if (unlikely(traced)) {
610 /* Preserve ptrace links if someone else is tracing this child. */ 602 /* Preserve ptrace links if someone else is tracing this child. */
@@ -620,13 +612,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
620 p->parent = p->real_parent; 612 p->parent = p->real_parent;
621 add_parent(p); 613 add_parent(p);
622 614
623 /* If we'd notified the old parent about this child's death, 615 if (p->state == TASK_TRACED) {
624 * also notify the new parent.
625 */
626 if (p->exit_state == EXIT_ZOMBIE && p->exit_signal != -1 &&
627 thread_group_empty(p))
628 do_notify_parent(p, p->exit_signal);
629 else if (p->state == TASK_TRACED) {
630 /* 616 /*
631 * If it was at a trace stop, turn it into 617 * If it was at a trace stop, turn it into
632 * a normal stop since it's no longer being 618 * a normal stop since it's no longer being
@@ -636,6 +622,27 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
636 } 622 }
637 } 623 }
638 624
625 /* If this is a threaded reparent there is no need to
626 * notify anyone anything has happened.
627 */
628 if (p->real_parent->group_leader == father->group_leader)
629 return;
630
631 /* We don't want people slaying init. */
632 if (p->exit_signal != -1)
633 p->exit_signal = SIGCHLD;
634
635 if (p->pdeath_signal)
636 /* We already hold the tasklist_lock here. */
637 group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
638
639 /* If we'd notified the old parent about this child's death,
640 * also notify the new parent.
641 */
642 if (!traced && p->exit_state == EXIT_ZOMBIE &&
643 p->exit_signal != -1 && thread_group_empty(p))
644 do_notify_parent(p, p->exit_signal);
645
639 /* 646 /*
640 * process group orphan check 647 * process group orphan check
641 * Case ii: Our child is in a different pgrp 648 * Case ii: Our child is in a different pgrp