On 08/27, Ananth N Mavinakayanahalli wrote: > > 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.
tracee == NULL when list_empty(->ptraced) == T. get_task_struct() is called when we know we do have tracees, if (!list_empty()) { tracee = list_first_entry(); get_task_struct(tracee); } in that case tracee != NULL Oleg.