Skip to content

Commit 0635285

Browse files
authored
Print task backtraces on sigquit (#59389)
1 parent f6e2483 commit 0635285

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

src/julia_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,7 @@ JL_DLLEXPORT jl_value_t *jl_backtrace_from_here(int returnsp, int skip);
15271527
void jl_fprint_critical_error(ios_t *t, int sig, int si_code, bt_context_t *context, jl_task_t *ct);
15281528
JL_DLLEXPORT void jl_raise_debugger(void) JL_NOTSAFEPOINT;
15291529
JL_DLLEXPORT void jl_gdblookup(void* ip) JL_NOTSAFEPOINT;
1530+
JL_DLLEXPORT void jl_print_task_backtraces(int show_done) JL_NOTSAFEPOINT;
15301531
void jl_fprint_native_codeloc(ios_t *s, uintptr_t ip) JL_NOTSAFEPOINT;
15311532
void jl_fprint_bt_entry_codeloc(ios_t *s, jl_bt_element_t *bt_data) JL_NOTSAFEPOINT;
15321533
#ifdef _OS_WINDOWS_

src/signal-handling.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,9 @@ void jl_fprint_critical_error(ios_t *s, int sig, int si_code, bt_context_t *cont
641641
jl_safe_fprintf(s, "\n[%d] signal %d (%d): %s\n", getpid(), sig, si_code, strsignal(sig));
642642
else
643643
jl_safe_fprintf(s, "\n[%d] signal %d: %s\n", getpid(), sig, strsignal(sig));
644+
if (sig == SIGQUIT) {
645+
jl_print_task_backtraces(0);
646+
}
644647
}
645648
jl_safe_fprintf(s, "in expression starting at %s:%d\n", jl_atomic_load_relaxed(&jl_filename), jl_atomic_load_relaxed(&jl_lineno));
646649
if (context && ct) {

src/stackwalk.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,11 +1397,19 @@ JL_DLLEXPORT void jl_print_backtrace(void) JL_NOTSAFEPOINT
13971397
// Print backtrace for specified task to `s`
13981398
JL_DLLEXPORT void jl_fprint_backtracet(ios_t *s, jl_task_t *t) JL_NOTSAFEPOINT
13991399
{
1400-
jl_task_t *ct = jl_current_task;
1401-
jl_ptls_t ptls = ct->ptls;
1402-
ptls->bt_size = 0;
1403-
jl_bt_element_t *bt_data = ptls->bt_data;
1404-
jl_record_backtrace_result_t r = jl_record_backtrace(t, bt_data, JL_MAX_BT_SIZE, 0);
1400+
jl_bt_element_t *bt_data;
1401+
jl_task_t *ct = jl_get_current_task();
1402+
size_t max_bt_size;
1403+
if (ct && ct->ptls != NULL) {
1404+
jl_ptls_t ptls = ct->ptls;
1405+
ptls->bt_size = 0;
1406+
bt_data = ptls->bt_data;
1407+
max_bt_size = JL_MAX_BT_SIZE;
1408+
} else {
1409+
max_bt_size = 1024; //8kb of stack should be safe
1410+
bt_data = (jl_bt_element_t *)alloca(max_bt_size * sizeof(jl_bt_element_t));
1411+
}
1412+
jl_record_backtrace_result_t r = jl_record_backtrace(t, bt_data, max_bt_size, 0);
14051413
size_t bt_size = r.bt_size;
14061414
size_t i;
14071415
for (i = 0; i < bt_size; i += jl_bt_entry_size(bt_data + i)) {

test/cmdlineargs.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,32 @@ let
7474
@test format_filename("%a%%b") == "a%b"
7575
end
7676

77+
if Sys.isunix()
78+
@testset "SIGQUIT prints task backtraces" begin
79+
script = """
80+
mutable struct RLimit
81+
cur::Int64
82+
max::Int64
83+
end
84+
const RLIMIT_CORE = 4 # from /usr/include/sys/resource.h
85+
ccall(:setrlimit, Cint, (Cint, Ref{RLimit}), RLIMIT_CORE, Ref(RLimit(0, 0)))
86+
write(stdout, "r")
87+
wait()
88+
"""
89+
exename = `$(Base.julia_cmd()) --startup-file=no --color=no`
90+
errp = PipeBuffer()
91+
# disable coredumps for this process
92+
p = open(pipeline(`$exename -e $script`, stderr=errp), "r")
93+
@test read(p, UInt8) == UInt8('r')
94+
Base.kill(p, Base.SIGQUIT)
95+
wait(p)
96+
err_s = readchomp(errp)
97+
@test Base.process_signaled(p) && p.termsignal == Base.SIGQUIT
98+
@test occursin("==== Thread ", err_s)
99+
@test occursin("==== Done", err_s)
100+
end
101+
end
102+
77103
@testset "julia_cmd" begin
78104
julia_basic = Base.julia_cmd()
79105
function get_julia_cmd(arg)

0 commit comments

Comments
 (0)