Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_
Expand Down
3 changes: 3 additions & 0 deletions src/signal-handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Member

@vtjnash vtjnash Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must gripe that having this now conditionally smashing bt_data just 5 lines before we need to use it for useful fatal backtraces is very annoying

}
}
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) {
Expand Down
18 changes: 13 additions & 5 deletions src/stackwalk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
26 changes: 26 additions & 0 deletions test/cmdlineargs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down