diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index d41779e8b3a..326fefa59ab 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1305,10 +1305,60 @@ pub fn init_env_logger(env: &str) { tracing::subscriber::set_global_default(subscriber).unwrap(); } +#[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, + ); + } + + 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); + } + } + + // 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(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(); + signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); let exit_code = catch_with_exit_code(|| {