Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

unwind: Finish up unwind when a task exits

On do_exit() when a task is exiting, if a unwind is requested and the
deferred user stacktrace is deferred via the task_work, the task_work
callback is called after exit_mm() is called in do_exit(). This means that
the user stack trace will not be retrieved and an empty stack is created.

Instead, add a function unwind_deferred_task_exit() and call it just
before exit_mm() so that the unwinder can call the requested callbacks
with the user space stack.

Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Indu Bhagat <indu.bhagat@oracle.com>
Cc: "Jose E. Marchesi" <jemarch@gnu.org>
Cc: Beau Belgrave <beaub@linux.microsoft.com>
Cc: Jens Remus <jremus@linux.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Sam James <sam@gentoo.org>
Link: https://lore.kernel.org/20250729182406.504259474@kernel.org
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

+25 -3
+3
include/linux/unwind_deferred.h
··· 39 39 int unwind_deferred_request(struct unwind_work *work, u64 *cookie); 40 40 void unwind_deferred_cancel(struct unwind_work *work); 41 41 42 + void unwind_deferred_task_exit(struct task_struct *task); 43 + 42 44 static __always_inline void unwind_reset_info(void) 43 45 { 44 46 struct unwind_task_info *info = &current->unwind_info; ··· 73 71 static inline int unwind_deferred_request(struct unwind_work *work, u64 *timestamp) { return -ENOSYS; } 74 72 static inline void unwind_deferred_cancel(struct unwind_work *work) {} 75 73 74 + static inline void unwind_deferred_task_exit(struct task_struct *task) {} 76 75 static inline void unwind_reset_info(void) {} 77 76 78 77 #endif /* !CONFIG_UNWIND_USER */
+2
kernel/exit.c
··· 68 68 #include <linux/rethook.h> 69 69 #include <linux/sysfs.h> 70 70 #include <linux/user_events.h> 71 + #include <linux/unwind_deferred.h> 71 72 #include <linux/uaccess.h> 72 73 #include <linux/pidfs.h> 73 74 ··· 939 938 940 939 tsk->exit_code = code; 941 940 taskstats_exit(tsk, group_dead); 941 + unwind_deferred_task_exit(tsk); 942 942 trace_sched_process_exit(tsk, group_dead); 943 943 944 944 /*
+20 -3
kernel/unwind/deferred.c
··· 114 114 /* Should always be called from faultable context */ 115 115 might_fault(); 116 116 117 - if (current->flags & PF_EXITING) 117 + if (!current->mm) 118 118 return -EINVAL; 119 119 120 120 if (!info->cache) { ··· 147 147 return 0; 148 148 } 149 149 150 - static void unwind_deferred_task_work(struct callback_head *head) 150 + static void process_unwind_deferred(struct task_struct *task) 151 151 { 152 - struct unwind_task_info *info = container_of(head, struct unwind_task_info, work); 152 + struct unwind_task_info *info = &task->unwind_info; 153 153 struct unwind_stacktrace trace; 154 154 struct unwind_work *work; 155 155 unsigned long bits; ··· 184 184 info->cache->unwind_completed |= BIT(work->bit); 185 185 } 186 186 } 187 + } 188 + 189 + static void unwind_deferred_task_work(struct callback_head *head) 190 + { 191 + process_unwind_deferred(current); 192 + } 193 + 194 + void unwind_deferred_task_exit(struct task_struct *task) 195 + { 196 + struct unwind_task_info *info = &current->unwind_info; 197 + 198 + if (!unwind_pending(info)) 199 + return; 200 + 201 + process_unwind_deferred(task); 202 + 203 + task_work_cancel(task, &info->work); 187 204 } 188 205 189 206 /**