On 04/16, Roland McGrath wrote: > > > OK. For the moment, please forget about these changes. Let's recall > > do_wait() has the ancient bug. wait_task_zombie() sets EXIT_DEAD > > unconditionally, then drops tasklist. If we are not the real_parent > > and the child was traced, we may restore >exit_state = EXIT_ZOMBIE > > later. But, if the ->real_parent calls do_wait() in between, it can > > see the child in EXIT_DEAD state and return -ECHLD. > > Really? Won't that do_wait hit (wait_consider_task): > > if (likely(!ptrace) && unlikely(p->ptrace)) {
Hmm, yes, its not that simple. Let me try again. Two threads T1 and T2, and some process X (not the child of T1/T2). T1 ptraces X. X exits and becomes zombie. T2 calls do_wait(WEXITED) and then wait_task_zombie(), it sets EXIT_DEAD and drops tasklist. T1 exits, calls exit_ptrace(). __ptrace_detach() does __ptrace_unlink() and nothing more. From now X->ptrace == 0. X->real_parent calls do_wait() and gets -ECHLD, because X is EXIT_DEAD and not traced. Of course, we can add the really nasty hacks to __ptrace_unlink() path, but I think we should never set EXIT_DEAD unless we know for sure the child will be released. > > (and we have other minor problems with EXIT_DEAD tasks on ->children). > > Which? Minor, but note the comment in find_new_reaper() about EXIT_DEAD tasks. I thought I can give more arguments against EXIT_DEAD task on ->children, but either I forgot, or they don't really exist ;) Anyway. I think it would be more cleaner if, everytime we set EXIT_DEAD, we also remove the task from list. The only problem is do_wait(), we need write_lock(tasklist) for this, and yes, write_lock() is not very nice. But as I said, this all is minor. > (We can make this a separate thread if it's not really apropos just > to ptrace.) Yes, I think it would be better to keep emails small. Change the subject. Oleg.