Skip to content

Commit 3bd0dc9

Browse files
committed
Install more signal stack trace handlers
1 parent 4229b80 commit 3bd0dc9

File tree

1 file changed

+36
-8
lines changed

1 file changed

+36
-8
lines changed

compiler/rustc_driver_impl/src/signal_handler.rs

+36-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ use std::{fmt, mem, ptr, slice};
66

77
use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
88

9+
/// Signals that represent that we have a bug, and our prompt termination has
10+
/// been ordered.
11+
#[rustfmt::skip]
12+
const KILL_SIGNALS: [(libc::c_int, &str); 3] = [
13+
(libc::SIGILL, "SIGILL"),
14+
(libc::SIGBUS, "SIGBUS"),
15+
(libc::SIGSEGV, "SIGSEGV")
16+
];
17+
918
unsafe extern "C" {
1019
fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int);
1120
}
@@ -39,8 +48,19 @@ macro raw_errln($tokens:tt) {
3948
/// # Safety
4049
///
4150
/// Caller must ensure that this function is not re-entered.
42-
unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
51+
unsafe extern "C" fn print_stack_trace(signum: libc::c_int) {
4352
const MAX_FRAMES: usize = 256;
53+
54+
let signame = {
55+
let mut signame = "<unknown>";
56+
for sig in KILL_SIGNALS {
57+
if sig.0 == signum {
58+
signame = sig.1;
59+
}
60+
}
61+
signame
62+
};
63+
4464
let stack = unsafe {
4565
// Reserve data segment so we don't have to malloc in a signal handler, which might fail
4666
// in incredibly undesirable and unexpected ways due to e.g. the allocator deadlocking
@@ -54,7 +74,8 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
5474
};
5575

5676
// Just a stack trace is cryptic. Explain what we're doing.
57-
raw_errln!("error: rustc interrupted by SIGSEGV, printing backtrace\n");
77+
raw_errln!("error: rustc interrupted by {signame}, printing backtrace\n");
78+
5879
let mut written = 1;
5980
let mut consumed = 0;
6081
// Begin elaborating return addrs into symbols and writing them directly to stderr
@@ -106,13 +127,18 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
106127
written += 1;
107128
}
108129
raw_errln!("note: we would appreciate a report at https://github.com/rust-lang/rust");
109-
// get the current stack size WITHOUT blocking and double it
110-
let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
111-
raw_errln!("help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}");
112-
written += 2;
130+
written += 1;
131+
if signum == libc::SIGSEGV {
132+
// get the current stack size WITHOUT blocking and double it
133+
let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
134+
raw_errln!(
135+
"help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}"
136+
);
137+
written += 1;
138+
}
113139
if written > 24 {
114140
// We probably just scrolled the earlier "we got SIGSEGV" message off the terminal
115-
raw_errln!("note: backtrace dumped due to SIGSEGV! resuming signal");
141+
raw_errln!("note: backtrace dumped due to {signame}! resuming signal");
116142
};
117143
}
118144

@@ -129,7 +155,9 @@ pub(super) fn install() {
129155
sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
130156
sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
131157
libc::sigemptyset(&mut sa.sa_mask);
132-
libc::sigaction(libc::SIGSEGV, &sa, ptr::null_mut());
158+
for (signum, _signame) in KILL_SIGNALS {
159+
libc::sigaction(signum, &sa, ptr::null_mut());
160+
}
133161
}
134162
}
135163

0 commit comments

Comments
 (0)