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.

Reply via email to