From 23259660030a583dd78f0d8f263ab5811fc9f75b Mon Sep 17 00:00:00 2001 From: Vikram Pal Date: Sat, 19 Dec 2020 08:50:33 +0000 Subject: [PATCH 1/3] Implement printing of stack traces on LLVM segfaults and aborts --- compiler/rustc_driver/src/lib.rs | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index c8891734ccec8..f2206746e2663 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1312,10 +1312,55 @@ pub fn init_env_logger(env: &str) { tracing::subscriber::set_global_default(subscriber).unwrap(); } +extern "C" { + // Only available in glibc + fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int); +} + +#[cfg(unix)] +fn print_stack_trace(_: libc::c_int) { + unsafe { + static mut STACK_TRACE: [*mut libc::c_void; 256] = [std::ptr::null_mut(); 256]; + let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), 256); + if depth == 0 { + return; + } + backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2); + } +} + +#[cfg(unix)] +// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the +// process, print a stack trace and then exit. +fn print_stack_trace_on_error_signal() { + unsafe { + const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; + let mut alt_stack: libc::stack_t = std::mem::zeroed(); + alt_stack.ss_sp = + std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked(ALT_STACK_SIZE, 1)) + as *mut libc::c_void; + alt_stack.ss_size = ALT_STACK_SIZE; + libc::sigaltstack(&mut alt_stack, std::ptr::null_mut()); + + let mut sa: libc::sigaction = std::mem::zeroed(); + sa.sa_sigaction = + print_stack_trace as fn(libc::c_int) as *mut libc::c_void as libc::sighandler_t; + sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK; + libc::sigemptyset(&mut sa.sa_mask); + libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); + } +} + +#[cfg(windows)] +// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the +// process, print a stack trace and then exit. +fn print_stack_trace_on_error_signal() {} + pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); init_rustc_env_logger(); + print_stack_trace_on_error_signal(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); let exit_code = catch_with_exit_code(|| { From ec6a85a5365374886fe4b1e2f4feb1d9270ec5da Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 2 Apr 2021 16:03:53 -0700 Subject: [PATCH 2/3] Small fixes --- compiler/rustc_driver/src/lib.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index f2206746e2663..dba95a8882618 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1312,16 +1312,17 @@ pub fn init_env_logger(env: &str) { tracing::subscriber::set_global_default(subscriber).unwrap(); } +#[cfg(unix)] extern "C" { - // Only available in glibc fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int); } #[cfg(unix)] -fn print_stack_trace(_: libc::c_int) { +extern "C" fn print_stack_trace(_: libc::c_int) { + const MAX_FRAMES: usize = 256; + static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] = [std::ptr::null_mut(); MAX_FRAMES]; unsafe { - static mut STACK_TRACE: [*mut libc::c_void; 256] = [std::ptr::null_mut(); 256]; - let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), 256); + let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32); if depth == 0 { return; } @@ -1332,35 +1333,34 @@ fn print_stack_trace(_: libc::c_int) { #[cfg(unix)] // When an error signal (such as SIGABRT or SIGSEGV) is delivered to the // process, print a stack trace and then exit. -fn print_stack_trace_on_error_signal() { +fn install_signal_handler() { unsafe { const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; let mut alt_stack: libc::stack_t = std::mem::zeroed(); alt_stack.ss_sp = - std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked(ALT_STACK_SIZE, 1)) + std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) as *mut libc::c_void; alt_stack.ss_size = ALT_STACK_SIZE; libc::sigaltstack(&mut alt_stack, std::ptr::null_mut()); let mut sa: libc::sigaction = std::mem::zeroed(); - sa.sa_sigaction = - print_stack_trace as fn(libc::c_int) as *mut libc::c_void as libc::sighandler_t; + sa.sa_sigaction = print_stack_trace as libc::sighandler_t; sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK; libc::sigemptyset(&mut sa.sa_mask); libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); } } -#[cfg(windows)] +#[cfg(not(unix))] // When an error signal (such as SIGABRT or SIGSEGV) is delivered to the // process, print a stack trace and then exit. -fn print_stack_trace_on_error_signal() {} +fn install_signal_handler() {} pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); init_rustc_env_logger(); - print_stack_trace_on_error_signal(); + install_signal_handler(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); let exit_code = catch_with_exit_code(|| { From 162ed4d7da65b6949ec8256825aa749245564d31 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 2 Jul 2021 00:20:04 +0000 Subject: [PATCH 3/3] Use signal handler only on supported platforms --- compiler/rustc_driver/src/lib.rs | 79 +++++++++++++++++--------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index dba95a8882618..b75f1d8290451 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1312,55 +1312,60 @@ pub fn init_env_logger(env: &str) { tracing::subscriber::set_global_default(subscriber).unwrap(); } -#[cfg(unix)] -extern "C" { - fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int); -} +#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))] +mod signal_handler { + extern "C" { + fn backtrace_symbols_fd( + buffer: *const *mut libc::c_void, + size: libc::c_int, + fd: libc::c_int, + ); + } -#[cfg(unix)] -extern "C" fn print_stack_trace(_: libc::c_int) { - const MAX_FRAMES: usize = 256; - static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] = [std::ptr::null_mut(); MAX_FRAMES]; - unsafe { - let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32); - if depth == 0 { - return; + extern "C" fn print_stack_trace(_: libc::c_int) { + const MAX_FRAMES: usize = 256; + static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] = + [std::ptr::null_mut(); MAX_FRAMES]; + unsafe { + let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32); + if depth == 0 { + return; + } + backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2); } - backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2); } -} -#[cfg(unix)] -// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the -// process, print a stack trace and then exit. -fn install_signal_handler() { - unsafe { - const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; - let mut alt_stack: libc::stack_t = std::mem::zeroed(); - alt_stack.ss_sp = - std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) - as *mut libc::c_void; - alt_stack.ss_size = ALT_STACK_SIZE; - libc::sigaltstack(&mut alt_stack, std::ptr::null_mut()); - - let mut sa: libc::sigaction = std::mem::zeroed(); - sa.sa_sigaction = print_stack_trace as libc::sighandler_t; - sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK; - libc::sigemptyset(&mut sa.sa_mask); - libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); + // When an error signal (such as SIGABRT or SIGSEGV) is delivered to the + // process, print a stack trace and then exit. + pub(super) fn install() { + unsafe { + const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; + let mut alt_stack: libc::stack_t = std::mem::zeroed(); + alt_stack.ss_sp = + std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) + as *mut libc::c_void; + alt_stack.ss_size = ALT_STACK_SIZE; + libc::sigaltstack(&mut alt_stack, std::ptr::null_mut()); + + let mut sa: libc::sigaction = std::mem::zeroed(); + sa.sa_sigaction = print_stack_trace as libc::sighandler_t; + sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK; + libc::sigemptyset(&mut sa.sa_mask); + libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); + } } } -#[cfg(not(unix))] -// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the -// process, print a stack trace and then exit. -fn install_signal_handler() {} +#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))] +mod signal_handler { + pub(super) fn install() {} +} pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); init_rustc_env_logger(); - install_signal_handler(); + signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); let exit_code = catch_with_exit_code(|| {