lkml.org 
[lkml]   [2004]   [Jul]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: zombie with CLONE_THREAD
    Here is the full version of my patch, in case you care.  It has the same
    effect as Andrea's variant. But I think this one doesn't introduce any new
    tests into the hot code path, which that one does.


    Thanks,
    Roland


    Signed-off-by: Roland McGrath <roland@redhat.com>


    --- linux-2.6.7-mm4/kernel/exit.c.~1~ 2004-06-30 16:29:06.000000000 -0700
    +++ linux-2.6.7-mm4/kernel/exit.c 2004-07-01 14:23:36.000000000 -0700
    @@ -537,7 +537,8 @@ static inline void choose_new_parent(tas
    BUG();
    }

    -static inline void reparent_thread(task_t *p, task_t *father, int traced)
    +static inline void reparent_thread(task_t *p, task_t *father, int traced,
    + struct list_head *to_release)
    {
    /* We don't want people slaying init. */
    if (p->exit_signal != -1)
    @@ -566,9 +567,12 @@ static inline void reparent_thread(task_
    /* If we'd notified the old parent about this child's death,
    * also notify the new parent.
    */
    - if (p->state == TASK_ZOMBIE && p->exit_signal != -1 &&
    - thread_group_empty(p))
    - do_notify_parent(p, p->exit_signal);
    + if (p->state == TASK_ZOMBIE) {
    + if (p->exit_signal == -1)
    + list_add(&p->ptrace_list, to_release);
    + else if (thread_group_empty(p))
    + do_notify_parent(p, p->exit_signal);
    + }
    }

    /*
    @@ -594,7 +598,8 @@ static inline void reparent_thread(task_
    * group, and if no such member exists, give it to
    * the global child reaper process (ie "init")
    */
    -static inline void forget_original_parent(struct task_struct * father)
    +static inline void forget_original_parent(struct task_struct * father,
    + struct list_head *to_release)
    {
    struct task_struct *p, *reaper = father;
    struct list_head *_p, *_n;
    @@ -615,18 +620,29 @@ static inline void forget_original_paren
    p = list_entry(_p,struct task_struct,sibling);
    if (father == p->real_parent) {
    choose_new_parent(p, reaper, child_reaper);
    - reparent_thread(p, father, 0);
    + reparent_thread(p, father, 0, to_release);
    } else {
    - ptrace_unlink (p);
    - if (p->state == TASK_ZOMBIE && p->exit_signal != -1 &&
    - thread_group_empty(p))
    - do_notify_parent(p, p->exit_signal);
    + BUG_ON(!p->ptrace);
    + __ptrace_unlink (p);
    + if (p->state == TASK_ZOMBIE) {
    + if (p->exit_signal == -1) {
    + /*
    + * This was only a zombie because
    + * we were tracing it. Now it should
    + * disappear as it would have done
    + * if we hadn't been tracing it.
    + */
    + list_add(&p->ptrace_list, to_release);
    + }
    + else if (thread_group_empty(p))
    + do_notify_parent(p, p->exit_signal);
    + }
    }
    }
    list_for_each_safe(_p, _n, &father->ptrace_children) {
    p = list_entry(_p,struct task_struct,ptrace_list);
    choose_new_parent(p, reaper, child_reaper);
    - reparent_thread(p, father, 1);
    + reparent_thread(p, father, 1, to_release);
    }
    }

    @@ -638,6 +654,7 @@ static void exit_notify(struct task_stru
    {
    int state;
    struct task_struct *t;
    + struct list_head ptrace_dead, *_p, *_n;

    if (signal_pending(tsk) && !tsk->signal->group_exit
    && !thread_group_empty(tsk)) {
    @@ -673,7 +690,8 @@ static void exit_notify(struct task_stru
    * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
    */

    - forget_original_parent(tsk);
    + INIT_LIST_HEAD(&ptrace_dead);
    + forget_original_parent(tsk, &ptrace_dead);
    BUG_ON(!list_empty(&tsk->children));

    /*
    @@ -759,6 +777,12 @@ static void exit_notify(struct task_stru
    _raw_write_unlock(&tasklist_lock);
    local_irq_enable();

    + list_for_each_safe(_p, _n, &ptrace_dead) {
    + list_del_init(_p);
    + t = list_entry(_p,struct task_struct,ptrace_list);
    + release_task(t);
    + }
    +
    /* If the process is dead, release it - nobody will wait for it */
    if (state == TASK_DEAD)
    release_task(tsk);
    -
    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/
    \
     
     \ /
      Last update: 2005-03-22 14:04    [W:0.027 / U:0.144 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site