Restore the necessary hooks in release_task() and exit_notify(), add the corresponding helpers into utrace.h.
Note: the @signal argument passed to ->report_death() does not match the previous behaviour. I think this shouldn't affect the current users, and I bet nobody can really understand what this magic argument should actually mean anyway.
Signed-off-by: Oleg Nesterov oleg@redhat.com --- include/linux/utrace.h | 22 ++++++++++++++++++++++ kernel/exit.c | 4 ++++ 2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/include/linux/utrace.h b/include/linux/utrace.h index 9a2e2f4..cf13839 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h @@ -697,4 +697,26 @@ static inline __must_check int utrace_barrier_pid(struct pid *pid,
#endif /* CONFIG_UTRACE */
+static inline void utrace_release_task(struct task_struct *task) +{ + /* see utrace_add_engine() about this barrier */ + smp_mb(); + if (task_utrace_flags(task)) + utrace_maybe_reap(task, task_utrace_struct(task), true); +} + +static inline void utrace_exit_notify(struct task_struct *task, + int signal, int group_dead) +{ + /* + * If utrace_set_events() was just called to enable + * UTRACE_EVENT(DEATH), then we are obliged to call + * utrace_report_death() and not miss it. utrace_set_events() + * checks @task->exit_state under tasklist_lock to synchronize + * with exit_notify(), the caller. + */ + if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) + utrace_report_death(task, group_dead, signal); +} + #endif /* linux/utrace.h */ diff --git a/kernel/exit.c b/kernel/exit.c index c1b0ab6..ba5ba22 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -168,6 +168,8 @@ void release_task(struct task_struct * p) struct task_struct *leader; int zap_leader; repeat: + utrace_release_task(p); + /* don't need to get the RCU readlock here - the process is dead and * can't be modifying its own credentials. But shut RCU-lockdep up */ rcu_read_lock(); @@ -860,6 +862,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) wake_up_process(tsk->signal->group_exit_task); write_unlock_irq(&tasklist_lock);
+ utrace_exit_notify(tsk, autoreap ? -1 : SIGCHLD, group_dead); + /* If the process is dead, release it - nobody will wait for it */ if (autoreap) release_task(tsk);