This patch fixes the following,
- race condition of ptrace flag
- sent odd signal to the tracer
- broken before behavior
And some cleanup.
Please apply.
-- OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>--- linux-2.5.35/kernel/exit.c~ 2002-09-16 17:41:59.000000000 +0900 +++ linux-2.5.35/kernel/exit.c 2002-09-16 17:28:01.000000000 +0900 @@ -221,7 +221,6 @@ void reparent_to_init(void) /* Set the exit signal to SIGCHLD so we signal init on exit */ current->exit_signal = SIGCHLD; - current->ptrace = 0; if ((current->policy == SCHED_NORMAL) && (task_nice(current) < 0)) set_user_nice(current, 0); /* cpus_allowed? */ @@ -464,50 +463,35 @@ static inline void forget_original_paren } list_for_each(_p, &father->ptrace_children) { p = list_entry(_p,struct task_struct,ptrace_list); + list_del_init(&p->ptrace_list); reparent_thread(p, reaper, child_reaper); + if (p->parent != p->real_parent) + list_add(&p->ptrace_list, &p->real_parent->ptrace_children); } } -static inline void zap_thread(task_t *p, task_t *father, int traced) +static inline void zap_thread(task_t *p, task_t *father) { - /* If someone else is tracing this thread, preserve the ptrace links. */ - if (unlikely(traced)) { - task_t *trace_task = p->parent; - int ptrace_flag = p->ptrace; - BUG_ON (ptrace_flag == 0); - - __ptrace_unlink(p); - p->ptrace = ptrace_flag; - __ptrace_link(p, trace_task); - } else { - /* - * Otherwise, if we were tracing this thread, untrace it. - * If we were only tracing the thread (i.e. not its real - * parent), stop here. - */ - ptrace_unlink (p); - if (p->parent != father) { - BUG_ON(p->parent != p->real_parent); - return; - } - list_del_init(&p->sibling); - p->parent = p->real_parent; - list_add_tail(&p->sibling, &p->parent->children); - } + ptrace_unlink(p); + remove_parent(p); + p->parent = p->real_parent; + add_parent(p, p->parent); if (p->state == TASK_ZOMBIE && p->exit_signal != -1) do_notify_parent(p, p->exit_signal); + /* * process group orphan check * Case ii: Our child is in a different pgrp * than we are, and it was the only connection * outside, so the child pgrp is now orphaned. */ - if ((p->pgrp != current->pgrp) && - (p->session == current->session)) { + if ((p->pgrp != father->pgrp) && + (p->session == father->session)) { int pgrp = p->pgrp; - if (__will_become_orphaned_pgrp(pgrp, 0) && __has_stopped_jobs(pgrp)) { + if (__will_become_orphaned_pgrp(pgrp, 0) && + __has_stopped_jobs(pgrp)) { __kill_pg_info(SIGHUP, (void *)1, pgrp); __kill_pg_info(SIGCONT, (void *)1, pgrp); } @@ -520,7 +504,7 @@ static inline void zap_thread(task_t *p, */ static void exit_notify(void) { - struct task_struct *t; + struct task_struct *t, *p; write_lock_irq(&tasklist_lock); @@ -580,10 +564,8 @@ static void exit_notify(void) if (current->exit_signal != -1) do_notify_parent(current, current->exit_signal); - while (!list_empty(¤t->children)) - zap_thread(list_entry(current->children.next,struct task_struct,sibling), current, 0); - while (!list_empty(¤t->ptrace_children)) - zap_thread(list_entry(current->ptrace_children.next,struct task_struct,ptrace_list), current, 1); + while ((p = eldest_child(current)) != NULL) + zap_thread(p, current); BUG_ON(!list_empty(¤t->children)); current->state = TASK_ZOMBIE; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/