On Tue, Aug 25, 2009 at 06:52:44PM +0200, Oleg Nesterov wrote:

...

>  void exit_ptrace(struct task_struct *tracer)
>  {
> -     struct task_struct *p, *n;
> -     LIST_HEAD(ptrace_dead);
> -
> -     write_lock_irq(&tasklist_lock);
> -     list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) {
> -             if (__ptrace_detach(tracer, p))
> -                     list_add(&p->ptrace_entry, &ptrace_dead);
> -     }
> -     write_unlock_irq(&tasklist_lock);
> +     for (;;) {
> +             struct task_struct *tracee = NULL;
> 
> -     BUG_ON(!list_empty(&tracer->ptraced));
> +             read_lock(&tasklist_lock);
> +             if (!list_empty(&tracer->ptraced)) {
> +                     tracee = list_first_entry(&tracer->ptraced,
> +                                     struct task_struct, ptrace_entry);
> +                     get_task_struct(tracee);
> +             }
> +             read_unlock(&tasklist_lock);
> +             if (!tracee)
> +                     break;

Can tracee be NULL? If so, get_task_struct() shouldn't be called
unconditionally above.

Ananth

Reply via email to