diff --git a/src/julia_internal.h b/src/julia_internal.h index 1980c861aed33..d494182b1f3ac 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1527,6 +1527,7 @@ JL_DLLEXPORT jl_value_t *jl_backtrace_from_here(int returnsp, int skip); void jl_fprint_critical_error(ios_t *t, int sig, int si_code, bt_context_t *context, jl_task_t *ct); JL_DLLEXPORT void jl_raise_debugger(void) JL_NOTSAFEPOINT; JL_DLLEXPORT void jl_gdblookup(void* ip) JL_NOTSAFEPOINT; +JL_DLLEXPORT void jl_print_task_backtraces(int show_done) JL_NOTSAFEPOINT; void jl_fprint_native_codeloc(ios_t *s, uintptr_t ip) JL_NOTSAFEPOINT; void jl_fprint_bt_entry_codeloc(ios_t *s, jl_bt_element_t *bt_data) JL_NOTSAFEPOINT; #ifdef _OS_WINDOWS_ diff --git a/src/signal-handling.c b/src/signal-handling.c index aff37b4bb433c..2a305c21e4fa8 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -639,6 +639,9 @@ void jl_fprint_critical_error(ios_t *s, int sig, int si_code, bt_context_t *cont jl_safe_fprintf(s, "\n[%d] signal %d (%d): %s\n", getpid(), sig, si_code, strsignal(sig)); else jl_safe_fprintf(s, "\n[%d] signal %d: %s\n", getpid(), sig, strsignal(sig)); + if (sig == SIGQUIT) { + jl_print_task_backtraces(0); + } } jl_safe_fprintf(s, "in expression starting at %s:%d\n", jl_atomic_load_relaxed(&jl_filename), jl_atomic_load_relaxed(&jl_lineno)); if (context && ct) { diff --git a/src/stackwalk.c b/src/stackwalk.c index db4039d01c18c..00347901c1f77 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -1397,11 +1397,19 @@ JL_DLLEXPORT void jl_print_backtrace(void) JL_NOTSAFEPOINT // Print backtrace for specified task to `s` JL_DLLEXPORT void jl_fprint_backtracet(ios_t *s, jl_task_t *t) JL_NOTSAFEPOINT { - jl_task_t *ct = jl_current_task; - jl_ptls_t ptls = ct->ptls; - ptls->bt_size = 0; - jl_bt_element_t *bt_data = ptls->bt_data; - jl_record_backtrace_result_t r = jl_record_backtrace(t, bt_data, JL_MAX_BT_SIZE, 0); + jl_bt_element_t *bt_data; + jl_task_t *ct = jl_get_current_task(); + size_t max_bt_size; + if (ct && ct->ptls != NULL) { + jl_ptls_t ptls = ct->ptls; + ptls->bt_size = 0; + bt_data = ptls->bt_data; + max_bt_size = JL_MAX_BT_SIZE; + } else { + max_bt_size = 1024; //8kb of stack should be safe + bt_data = (jl_bt_element_t *)alloca(max_bt_size * sizeof(jl_bt_element_t)); + } + jl_record_backtrace_result_t r = jl_record_backtrace(t, bt_data, max_bt_size, 0); size_t bt_size = r.bt_size; size_t i; for (i = 0; i < bt_size; i += jl_bt_entry_size(bt_data + i)) { diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 526aa833c7544..b29662b65706d 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -74,6 +74,32 @@ let @test format_filename("%a%%b") == "a%b" end +if Sys.isunix() + @testset "SIGQUIT prints task backtraces" begin + script = """ + mutable struct RLimit + cur::Int64 + max::Int64 + end + const RLIMIT_CORE = 4 # from /usr/include/sys/resource.h + ccall(:setrlimit, Cint, (Cint, Ref{RLimit}), RLIMIT_CORE, Ref(RLimit(0, 0))) + write(stdout, "r") + wait() + """ + exename = `$(Base.julia_cmd()) --startup-file=no --color=no` + errp = PipeBuffer() + # disable coredumps for this process + p = open(pipeline(`$exename -e $script`, stderr=errp), "r") + @test read(p, UInt8) == UInt8('r') + Base.kill(p, Base.SIGQUIT) + wait(p) + err_s = readchomp(errp) + @test Base.process_signaled(p) && p.termsignal == Base.SIGQUIT + @test occursin("==== Thread ", err_s) + @test occursin("==== Done", err_s) + end +end + @testset "julia_cmd" begin julia_basic = Base.julia_cmd() function get_julia_cmd(arg)