If ->report_xxx() returns UTRACE_STOP the tracee will do utrace_stop eventually. But how can the tracer know the tracee is already TASK_TRACED/->stopped?
(except it can check utrace_control(UTRACE_STOP) in a loop of course). Actually, I am asking because this chunk from utrace-ptrace.patch +#ifdef CONFIG_UTRACE_PTRACE + /* + * If ptrace is among the reasons for this stop, do its + * notification now. This could not just be done in + * ptrace's own event report callbacks because it has to + * be done after we are in TASK_TRACED. This makes the + * synchronization with ptrace_do_wait() work right. + */ + if (((task->ptrace >> 16) & UTRACE_RESUME_MASK) == + UTRACE_RESUME - UTRACE_STOP) { + read_lock(&tasklist_lock); + do_notify_parent_cldstop(task, CLD_TRAPPED); + read_unlock(&tasklist_lock); + } +#endif Looks like a horrible hack, imho. Utrace should know nothing about ptrace. Can't we do something like --- include/linux/utrace.h +++ include/linux/utrace.h @@ -170,6 +170,7 @@ void task_utrace_proc_status(struct seq_ */ enum utrace_resume_action { UTRACE_STOP, + UTRACE_STOP_NOTIFY, UTRACE_REPORT, UTRACE_INTERRUPT, UTRACE_SINGLESTEP, @@ -512,6 +513,9 @@ static inline void utrace_engine_put(str * parent by blocking. */ struct utrace_engine_ops { + // SPECIAL!!! must not block/etc + void (*notify_stopped)(...); + u32 (*report_quiesce)(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *task, --- kernel/utrace.c +++ kernel/utrace.c @@ -419,6 +419,13 @@ static bool utrace_stop(struct task_stru spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); + list_for_each_entry(engine) { + if (engine_wants_notify_stopped(engine)) { + clear_engine_wants_notify_stopped(engine); + engine->ops->notify_stopped(...); + } + } + schedule(); @@ -1348,6 +1355,11 @@ static bool finish_callback(struct utrac { enum utrace_resume_action action = utrace_resume_action(ret); + if (action == UTRACE_STOP_NOTIFY) { + mark_engine_wants_notify_stopped(engine); + action = UTRACE_STOP; + } + report->result = ret & ~UTRACE_RESUME_MASK; /* ? Or do you think this doesn't make sense? (of course, the "patch" above is just to explain what I mean, we need more changes with ENGINE_STOP mask, utrace_control, utrace_set_events, etc). Oleg.