In short: how can the tracer do UTRACE_DETACH and make sure it doesn't leave the tracee in TASK_TRACED state?
My concern is ptrace, but I think thw question is about utrace in general. There is no way to "cancel" utrace_stop() if it didn't take utrace->lock yet. ptrace(PTRACE_DETACH) is easy. The tracee is stopped or killed. But what about the implicit detach from exit_ptrace() ? Suppose the tracer calls utrace_control(UTRACE_DETACH) right before the tracee calls utrace_stop(). What can we do then? The tracer can't know the tracee is going to stop, the tracee can't know it should not stop. (I am ignoring the case when there are other tracers). If the tracer calls utrace_barrier() after UTRACE_DETACH, it will spin until the TASK_TRACED tracee is killed, get_utrace_lock() will notice utrace_detached_ops and return -ERESTARTSYS. It seems to me utrace.c needs some changes to help, no? Looks like, utrace_stop() should re-check engines after spin_lock() and do something similar to what utrace_reset() reset does. Also. I think this re-check should look again at engine_wants_stop(), this can help to avoid the races with utrace_wakeup(). IOW, how about something like static bool utrace_stop_trylock(...) { bool should_stop; again; spin_lock(&utrace->lock); should_stop = false; list_for_each_entry_safe(engine, next, &utrace->attached, entry) { if (engine->ops == &utrace_detached_ops) { utrace_reset(); goto again; } should_stop ||= engine_wants_stop(engine); } if (!should_stop) spin_unlock(&utrace->lock); return should_stop; } Then, utrace_stop() is changed - spin_lock(&utrace->lock); + if (!utrace_stop_trylock(...)) + return; Thoughts? (I don't really think utrace_stop_trylock() (the name is random) should actually call utrace_reset(), just to explain what I mean). Oleg.