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.