On 10/19, Roland McGrath wrote:
>
> > Yes. But, with this patch, in this case
> > utrace_barrier()->get_utrace_lock(attached => false) returns success
> > and then we check utrace->reporting == engine.
>
> I guess that's OK if ->reporting == engine is always set when any kind of
> callback might be in progress.

I think utrace_maybe_reap() is the only exception,

> > (Hmm. Probably utrace->reap = T case needs more attention,
> >  utrace_maybe_reap() doesn't set utrace->reporting).
>
> That would be a problem.

Yes, but the current code has the same problem? Hmm, I need to
recheck this all once again tomorrow. Suddenly I started to suspect
that even ->ops == NULL case is not right. And the more I read this
code now, the more I confused.

But in any case. If engine->ops == &utrace_detached_ops and
utrace->reporting != engine, I do not see why utrace_barrier() can't
return success, even if utrace->reap is set.

> > But, unfortunately, this signal_pending() check assumes the caller can
> > always handle this ERESTARTSYS. But this is not true, one example is
> > the exiting debugger doing exit_ptrace().
>
> I understand it's a problem.  Perhaps we need to have a flag argument or
> (probably better) a new utrace_barrier_uninterruptible call.  But, for
> this particular situation with exit_ptrace, it could be kludged around.
> The caller is never going to dequeue another signal once it's as far
> into death as exit_ptrace anyway.  So, it could do a loop of:
>
>       ret = utrace_barrier(task, engine);
>       if (ret == -ERESTARTSYS) {
>               clear_thread_flag(TIF_SIGPENDING);
>               continue;
>       }

Yes, the workaround is simple. But this is the same uninterruptible spin.

And, ptrace-utrace has another reason for utrace_barrier_uninterruptible().
"ptrace: ptrace_reuse_engine()->utrace_barrier() should ignore ERESTARTSYS"
adds

        static int utrace_barrier_uninterruptible(struct task_struct *target,
                                                struct utrace_engine *engine)
        {
                for (;;) {
                        int err = utrace_barrier(target, engine);

                        if (err != -ERESTARTSYS)
                                return err;

                        schedule_timeout_uninterruptible(1);
                }
        }

for ptrace_detach_task() and ptrace_reuse_engine(). Today I tried to
avoid it in ptrace_reuse_engine() path, but I don't see any solution.
Even if fatal_signal_pending() is true, we can't just abort attaching.

Oleg.

Reply via email to