On 03/15, Roland McGrath wrote:
>
> > Then we re-do this (well, almost) check under ->siglock,
> >
> >     } else if (task_is_stopped(target)) {
> >             if (!(target->utrace_flags & UTRACE_EVENT(JCTL)))
> >                     utrace->stopped = stopped = true;
> >     }
> >
> > But this is not nice. Let's suppose the task is already stopped, we do
> > UTRACE_ATTACH + utrace_set_events(JCTL).
>
> This is exactly why utrace_set_events() sets ->stopped preemptively for
> that case.

Yes, thanks. I saw this code in utrace_set_events(), but then forgot.

> >     REPORT(task, utrace, &report, UTRACE_EVENT(JCTL),
> >            report_jctl, what, notify);
> >
> > instead.
>
> There is a bug, but your fix changes a key API choice.
> I've put in this fix:
>
> -            report_jctl, was_stopped ? CLD_STOPPED : CLD_CONTINUED, what);
> +            report_jctl, was_stopped ? CLD_STOPPED : CLD_CONTINUED,
> +            notify ? what : 0);
>
> The @type argument shows the state we will be in after the callback.
> If the state changes, there will be another callback.  That's what a
> state-tracking tracer needs, e.g. to keep a little light on the screen red
> while the thread is stopped and green while it's running.
>
> The @notify argument shows what SIGCHLD the parent sees (if it were
> dequeuing all possible SIGCHLD postings as quickly as they come).  That's
> what an event-tracking tracer needs, e.g. to match up with what SIGCHLDs
> are expected in the parent.

I see, thanks.

> > With the first patch, we call utrace_report_jctl() before we actually
> > stop. do_signal_stop() can fail then, but I think this is OK, we can
> > pretend that SIGCONT/SIGKILL happened after we stopped. It is not complete,
> > and with this patch we always call ->report_jctl with notify == 0. Just for
> > discussion.
>
> I think I sort of understand the intent of your patch.  If we change the
> calling convention for tracehook_notify_jctl, I think we want to preserve
> the aspect that the hook decides about sending the notification.  That's
> how the ptrace quirks can be reimplemented differently later without
> changing the tracehook layer again.  Also, we certainly don't want one
> tracehook call with two different locking conditions.

Agreed, "bool sig_locked" is awful. But we can avoid it. The real problem
is how to figure out the correct "notify" argument. I'll try to think more,
but I am not sure I will find the clean solution :(

Just in case. We can introduce PF_SIGCONTED flag and change
prepare_signal(SIGCONT) and signal_wake_up(resume => 1) to set this flag.
Since the task never changes its ->flags in finish_stop() path, it is safe
to do this under ->siglock. This way utrace_report_jctl() can drop
TASK_STOPPED before REPORT() and then check !PF_SIGCONTED before restoring
the ->state. But yes sure, this is very, very ugly.

Oleg.

Reply via email to