On 07/21, Roland McGrath wrote: > > > For example, utrace_control(UTRACE_STOP)->utrace_do_stop() finds > > the child inside utrace_report_jctl() path in TASK_STOPPED state, > > Where? utrace_report_jctl is called with the siglock held, and resets > to TASK_RUNNING before it unlocks. > > > sets utrace->stopped and returns true. After that utrace_report_jctl() > > clears ->stopped and another engine's ->report_jctl does mutex_lock() > > and sets ->state == TASK_INTERRUPTIBLE. > > TASK_STOPPED should never be seen (by someone holding the siglock, like > utrace_do_stop does) until after all ->report_jctl hooks have finished.
Well yes, this particular scenario is not possible, but... OK, please forget about this for the moment. Why utrace_report_jctl() and utrace_get_signal() have to clear ->stopped ? Because unlike utrace_stop(), do_signal_stop() does not do finish_utrace_stop(). This means that utrace_report_jctl() and utrace_get_signal() might be called with ->stopped == true, ->stopped can be set by UTRACE_STOP/UTRACE_DETACH while we were stopped _before_. (btw, I think the comment in utrace_report_jctl() above "->stopped = 0" is confusing, it looks as if we are trying to prevent the race with utrace_do_stop() which was called after the caller sets TASK_STOPPED). Now return to the problem. It is even simpler (and worse) than I thought. Let's suppose the tracee is TASK_STOPPED, and the tracer does ptrace_check_attach(). utrace_control(UTRACE_STOP) sets ->stopped = true. But, the tracee is still TASK_STOPPED, not TASK_TRACED, SIGCONT can wake it up ? This means ptrace_check_attach() can succeed but the tracee can even return to the user-space after that, no? There is no guarantee utrace_get_signal() will call finish_resume_report(). For example, if there are no pending signals, we just clear ->stopped and return after dequeue_signal(). Oh, I hope I missed something. Oleg.