On 10/28, Roland McGrath wrote:
>
> I've made a new branch, utrace-cleanup.
> This forks from utrace-indirect and has:
>
> 26fefca utrace: sticky resume action
> 28b2774 utrace: remove ->stopped field
I am not sure I understand the new code in details - too much changes.
Anyway, I can never understand the code after the first reading. At
first glance, imho this change is "right in general" but:
1. This breaks the current implementation of utrace-ptrace.
I guess I misunderstood you when we discussed this before, I thought
that the tracee should handle UTRACE_SINGLESTEP right after resume
and call user_enable_single_step(). However, enable_step() is called
at utrace_resume/utrace_get_signal time, this is too late for ptrace.
I guess this branch is the code which will be sent to lkml, right?
In this case utrace-cleanup should be merged into utrace-ptrace right
now, then I need to fix ptrace. Basically, ptrace_report_quiesce() and
ptrace_report_interrupt() should detect the case when the tracee was
resumed by PTRACE_XXXSTEP and then it passed syscall_trace_leave()
without TIF_SINGLESTEP, and synthesize a trap.
The main problem is that this is not consistent across the different
arch'es :[
2. Cosmetic, but the usage of utrace_task_alloc() looks a bit strange.
Why it returns bool, not struct utrace * ?
3. Now that we have utrace->resume, can't we kill report->resume_action ?
4. One of the changes in utrace_get_signal() doesn't look exactly right.
if (utrace->resume < UTRACE_RESUME || utrace->signal_handler) {
...
if (resume > UTRACE_REPORT) {
report.action = resume;
finish_resume_report(&report);
}
Yes, we need finish_resume_report() here, but since report->takers
is not set, finish_report_reset() will always call utrace_reset().
OTOH, we can't set ->takers before finish_resume_report(), we can
miss UTRACE_DETACH request. utrace_control(DETACH)->utrace_do_stop()
does not change utrace->resume != UTRACE_RESUME.
And since utrace_do_stop() never "upgrades" utrace->resume, we have
another problem: UTRACE_STOP request can be lost here.
5. utrace_resume() has the same problems. If report->action != REPORT
we do not call callbacks and finish_resume_report() is called with
->takers == F.
6. But! I think utrace_resume() was always wrong here. Because it
calls start_callback(events => 0) and thus we nevet set ->takers.
7. utrace_attach_task() has an implicit wmb() between "->utrace = new_utrace"
and "->utrace_flags = REAP", this is good.
But, for example, tracehook_force_sigpending() does not have rmb(),
this means utrace_interrupt_pending() can OOPS in theory.
8. Completely off-topic, but utrace_control() has a very strange comment
under "case UTRACE_INTERRUPT",
* When it's stopped, we know it's always going
* through utrace_get_signal() and will recalculate.
can't recall if it were ever true, but surely it is not now?
Oleg.