On 09/23, Roland McGrath wrote: > > > OK, finish_callback_report() and utrace_control(DETACH) can set > > TIF_NOTIFY_RESUME. > > Right. Those utrace_resume has the report.action==UTRACE_RESUME bail-out > case. So either that would change or detach would also do UTRACE_REPORT. > > > But what if there are no more attached engines? > > Looks like, utrace_resume(UTRACE_RESUME) needs to handle this special > > case. And utrace_reset() shouldn't clear task->utrace_flags, otherwise > > utrace_resume/utrace_get_signal won't be called. > > Right. Or else tracehook_notify_resume could call utrace_resume > unconditionally, but I'm not at all sure that is not worse. The > original theory was that it should always be OK to have some > utrace_flags bits stay set when they are "stale", because any kind of > reporting pass that got enabled would hit the report->spurious case > and clean the state up synchronously when it's safe.
I tried to make the patch which addresses this issue, but surprisingly I failed. Because I think there are more (minor) problems here. When it comes to multitracing, we can have the unwanted trap even without detaching. In short: I no longer understand why utrace->resume can be UTRACE_*STEP when the tracee is stopped, and in fact I think this is not right. For example. Consider two engines, E1 and E2. To simplify the discussion suppose that both engines have engine->data->resume and ->report_quiesce() just returns ->resume. So, if the debugger wants, say, single-step, it does engine->data->resume = UTRACE_SINGLESTEP; utrace_control(UTRACE_SINGLESTEP); Actually, any engine should do something like this. Now suppose that E1 wants UTRACE_SINGLESTEP, E2 asks for UTRACE_STOP. In this case utrace_resume() results in utrace_stop() which sets utrace->resume = UTRACE_SINGLESTEP before sleeping. First of all - why? Yes, the theory is that we have another reporting loop after wake_up, but utrace->resume = UTRACE_REPORT is enough, E1 should always acquire UTRACE_SINGLESTEP if needed or it is buggy. But more importantly, this doesn't look right or I missed something. Suppose that, before E2 resumes the tracee, E1 does utrace_control(STOP) which immediately succeeds and allows E1 to play with the stopped tracee. Again, to simplify the discussion, suppose that E2 does UTRACE_RESUME and nothing more after that. Now. E1 wants to resume the tracee too and it does engine->data->resume = UTRACE_RESUME; utrace_control(UTRACE_RESUME); utrace_control(RESUME) correctly clears TIF_SINGLESTEP, but it doesn't change utrace->resume. This means utrace_resume() doesn't do the reporting loop, it just calls user_enable_single_step() and returns to user-mode. So. Could you explain why utrace_stop() should ever keep UTRACE_STEP in utrace->resume? finish_report() does the same but this looks fine. Also. I am not sure utrace_control(UTRACE_STEP) should always set utrace->resume = UTRACE_STEP. If the tracee is stopped but there is another ENGINE_STOP engine (iow, the tracee won't be resumed right now) we have the same problem. Off-topic, #define UTRACE_RESUME_BITS (ilog2(UTRACE_RESUME_MAX) + 1) why UTRACE_RESUME_MAX? it should be (ilog2(UTRACE_RESUME_MAX - 1) + 1), no? Oleg.