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 <o...@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);
-- 
1.5.5.1


Reply via email to