Ananth N Mavinakayanahalli wrote: > > --- utrace-6mar.orig/kernel/utrace.c > +++ utrace-6mar/kernel/utrace.c > @@ -123,12 +123,15 @@ static inline bool exclude_utrace(struct > */ > static inline int utrace_attach_delay(struct task_struct *target) > { > - if ((target->flags & PF_STARTING) && target->real_parent != current) > - do { > - schedule_timeout_interruptible(1); > - if (signal_pending(current)) > - return -ERESTARTNOINTR; > - } while (target->flags & PF_STARTING); > + if ((target->flags & PF_STARTING) && target->real_parent != current) { > + if (target->real_parent != current->real_parent) {
But target->real_parent == current->real_parent doesn't mean current is a creator? It is possible that current's ->real_parent does fork(). And even with CLONE_THREAD, this doesn't mean we are creator, but the commment says "The creator gets the first chance to attach". Perhaps we can intruduce the new UTRACE_ATTACH_XXX, this flags should be used when utrace_attach_task() is called from ->report_clone(), and then something like --- kernel/utrace.c +++ kernel/utrace.c @@ -130,12 +130,11 @@ static inline bool exclude_utrace(struct */ static inline int utrace_attach_delay(struct task_struct *target) { - if ((target->flags & PF_STARTING) && target->real_parent != current) - do { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - return -ERESTARTNOINTR; - } while (target->flags & PF_STARTING); + while (unlikely(target->flags & PF_STARTING)) { + schedule_timeout_interruptible(1); + if (signal_pending(current)) + return -ERESTARTNOINTR; + } return 0; } @@ -267,7 +266,8 @@ struct utrace_engine *utrace_attach_task engine->ops = ops; engine->data = data; - ret = utrace_attach_delay(target); + if (!(flags & UTRACE_ATTACH_XXX)) + ret = utrace_attach_delay(target); if (likely(!ret)) ret = utrace_add_engine(target, utrace, engine, flags, ops, data); when ->report_clone() is called current == creator always. Yes, this is ugly, I agree. We can also add "struct task_struct *creator" to "struct utrace". It is be set by tracehook_finish_clone/utrace_init_task, and it is cleared by tracehook_report_clone() path. In that case we do not need PF_STARTING. But this blows task_struct... Oleg.