On 03/03, Roland McGrath wrote: > > I would rather not touch the tracehook interfaces now. You are indeed > right that the motivation for this had to do with the utrace-indirect code. > As I've said, I do intend to resurrect that code and send it upstream later > on. We can consider cleanups then. For now, let's not do anything > preemptively that is likely to introduce a new need to touch non-utrace > code again later.
OK, understand, thanks. A couple of questions... utrace_attach_task() checks ->exit_state == EXIT_DEAD. Why? I mean, how can it help, we don't hold any locks, target can change its ->exit_state right after the check. So, looks like we can attach to the EXIT_DEAD target. Is it safe? The only in-kernel user of utrace is ptrace, in that case I _think_ we are safe, we should notice that the task is dead later, for example in get_utrace_lock(), and do UTRACE_DETACH. But in general, is it OK? Hmm... utrace_release_task() checks only ->attached, I can't understand why it ignores ->attaching. Let's suppose we are doing PTRACE_ATTACH to the exiting task, isn't it possible to leak the attached engine? I don't understand why utrace_release_task() doesn't set ->reap = 1 unconditionally. In that case we could use this flag instead of EXIT_DEAD to verify it is "safe" to attach or get_utrace_lock(). Back to utrace_attach_task(), static inline int utrace_attach_delay(struct task_struct *target) { if (target->flags & PF_STARTING) { struct utrace *utrace = task_utrace_struct(current); if (!utrace || utrace->cloning != target) { yield(); if (signal_pending(current)) return -ERESTARTNOINTR; return -EAGAIN; Why does it call yield() before returning the error? This looks really strange. And what is the point to check signal_pending() here? (btw, "!utrace" above is not possible). Oleg.