From d89b96b3fc7ac13ed29ac1508ba302dc4f758d33 Mon Sep 17 00:00:00 2001 From: Kiran Date: Sat, 15 Oct 2022 16:43:05 -0400 Subject: [PATCH] Add `jl_print_task_backtraces()` (#46845) Iterates through `jl_all_tls_states` and through all `live_tasks` in `ptls->heap`, printing backtraces. --- src/stackwalk.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/stackwalk.c b/src/stackwalk.c index d64727dea8ba6..7b6e248a9cb5c 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -722,7 +722,7 @@ static void JuliaInitializeLongjmpXorKey(void) } #endif -JL_UNUSED static uintptr_t ptr_demangle(uintptr_t p) +JL_UNUSED static uintptr_t ptr_demangle(uintptr_t p) JL_NOTSAFEPOINT { #if defined(__GLIBC__) #if defined(_CPU_X86_) @@ -854,7 +854,7 @@ _os_ptr_munge(uintptr_t ptr) extern bt_context_t *jl_to_bt_context(void *sigctx); -void jl_rec_backtrace(jl_task_t *t) +void jl_rec_backtrace(jl_task_t *t) JL_NOTSAFEPOINT { jl_task_t *ct = jl_current_task; jl_ptls_t ptls = ct->ptls; @@ -1104,7 +1104,9 @@ JL_DLLEXPORT void jlbacktrace(void) JL_NOTSAFEPOINT jl_print_bt_entry_codeloc(bt_data + i); } } -JL_DLLEXPORT void jlbacktracet(jl_task_t *t) + +// Print backtrace for specified task +JL_DLLEXPORT void jlbacktracet(jl_task_t *t) JL_NOTSAFEPOINT { jl_task_t *ct = jl_current_task; jl_ptls_t ptls = ct->ptls; @@ -1121,6 +1123,42 @@ JL_DLLEXPORT void jl_print_backtrace(void) JL_NOTSAFEPOINT jlbacktrace(); } +// Print backtraces for all live tasks, for all threads. +// WARNING: this is dangerous and can crash if used outside of gdb, if +// all of Julia's threads are not stopped! +JL_DLLEXPORT void jl_print_task_backtraces(void) JL_NOTSAFEPOINT +{ + for (size_t i = 0; i < jl_n_threads; i++) { + jl_ptls_t ptls2 = jl_all_tls_states[i]; + arraylist_t *live_tasks = &ptls2->heap.live_tasks; + size_t n = live_tasks->len; + jl_safe_printf("==== Thread %d created %zu live tasks\n", + ptls2->tid + 1, n + 1); + jl_safe_printf(" ---- Root task (%p)\n", ptls2->root_task); + jl_safe_printf(" (sticky: %d, started: %d, state: %d, tid: %d)\n", + ptls2->root_task->sticky, ptls2->root_task->started, + jl_atomic_load_relaxed(&ptls2->root_task->_state), + jl_atomic_load_relaxed(&ptls2->root_task->tid) + 1); + jlbacktracet(ptls2->root_task); + + void **lst = live_tasks->items; + for (size_t j = 0; j < live_tasks->len; j++) { + jl_task_t *t = (jl_task_t *)lst[j]; + jl_safe_printf(" ---- Task %zu (%p)\n", j + 1, t); + jl_safe_printf(" (sticky: %d, started: %d, state: %d, tid: %d)\n", + t->sticky, t->started, jl_atomic_load_relaxed(&t->_state), + jl_atomic_load_relaxed(&t->tid) + 1); + if (t->stkbuf != NULL) + jlbacktracet(t); + else + jl_safe_printf(" no stack\n"); + jl_safe_printf(" ---- End task %zu\n", j + 1); + } + jl_safe_printf("==== End thread %d\n", ptls2->tid + 1); + } + jl_safe_printf("==== Done\n"); +} + #ifdef __cplusplus } #endif