Roland, I left some parts of your message unanswered because I need to think more about them...
On 03/12, Roland McGrath wrote: > > > But, if we enter utrace_report_jctl() with ->stopped == 1, JCTL can be > > already removed from ->utrace_flags, exactly because ->stopped was true. > > I don't follow this. JCTL is never "removed" from ->utrace_flags, except > as all event bits are, by utrace_reset(). Yep. And utrace_reset() can be called because ->stopped == 1. Let me explain. Again, let's suppose D attaches engine E to the target T. T enters utrace_report_jctl() with ->stopped == 1. D calls utrace_set_events(events => 0), this removes JCTL from E->flags. D calls, say, utrace_control(UTRACE_RESUME). Since ->stopped == 1, this calls utrace_reset() and removes JCTL from T->utrace_flags. T takes utrace->lock, clears ->stopped, and drops the lock. D does utrace_control(UTRACE_STOP). This calls utrace_do_stop() which sees task_is_stopped() && !JCTL, so it sets ->stopped = true. T calls REPORT() and start_report() hits the (correct) BUG_ON(stopped). No? > > This leads to another minor question, how it is possible to enter enter > > utrace_report_jctl() with ->stopped == 1 ? I think the only possibility > > it was previously set by another call to utrace_report_jctl(), see below. > > There are two ways to enter utrace_report_jctl with ->stopped set. > > 1. utrace_report_jctl was called when entering TASK_STOPPED, and set it then. > Now utrace_report_jctl is called for the CLD_CONTINUED case, and > ->stopped remains set. this is covered by my guess above, > 2. utrace_set_events(target, UTRACE_EVENT(JCTL)) was called when target was > already in TASK_STOPPED (and really stopped, or at least got past > tracehook_notify_jctl before JCTL was set). It sets ->stopped before > adding JCTL to ->utrace_flags, Yes, thanks. I missed this. > > SIGNAL_STOP_STOPPED is not reliable, it is possible that the group stop in > > progress and it is not finished yet. > > SIGNAL_STOP_STOPPED should be reliable, as far as it goes. It will only be > set if the group stop is complete. Yes sure. I wasn't clear. I meant, what if SIGNAL_STOP_STOPPED is not set? This doesn't mean we don't need __set_current_state(TASK_STOPPED), it is possible that the group-stop is in progress and ->group_stop_count != 0. > > But! can't we miss utrace_wakeup() ? > > I think you've found something (though not quite the scenario you describe). > > > Let's suppose the debugger D attaches the single engine E to the target T. > > > > D does utrace_set_events(JCTL). > > > > T calls do_signal_stop(), tracehook_notify_jctl() sees JCTL and starts > > utrace_report_jctl(). > > > > D does utrace_set_events(events => 0), this clears E->flags. > > > > T calls REPORT(), nobody needs needs JCTL, finish_report() sees > > !->takers > > and calls utrace_reset(). It sets ->utrace_flags = 0. > > Nope: > > flags |= engine->flags | UTRACE_EVENT(REAP); Ah, thanks. Can't understand how I didn't notice this, I checked the code several times ;) But as you pointed out, > So, change your scenario to: > > D does utrace_control(UTRACE_DETACH). > > and then this will happen. Yes. Oleg.