@@ -6,6 +6,15 @@ use std::{fmt, mem, ptr, slice};
66
77use 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+
918unsafe 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
@@ -94,7 +115,7 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
94115 written += rem. len ( ) + 1 ;
95116
96117 let random_depth = || 8 * 16 ; // chosen by random diceroll (2d20)
97- if cyclic || stack. len ( ) > random_depth ( ) {
118+ if ( cyclic || stack. len ( ) > random_depth ( ) ) && signum == libc :: SIGSEGV {
98119 // technically speculation, but assert it with confidence anyway.
99120 // rustc only arrived in this signal handler because bad things happened
100121 // and this message is for explaining it's not the programmer's fault
@@ -106,17 +127,22 @@ 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 {
114- // We probably just scrolled the earlier "we got SIGSEGV " message off the terminal
115- raw_errln ! ( "note: backtrace dumped due to SIGSEGV ! resuming signal" ) ;
140+ // We probably just scrolled the earlier "interrupted by {signame} " message off the terminal
141+ raw_errln ! ( "note: backtrace dumped due to {signame} ! resuming signal" ) ;
116142 } ;
117143}
118144
119- /// When SIGSEGV is delivered to the process, print a stack trace and then exit.
145+ /// When one of the KILL signals is delivered to the process, print a stack trace and then exit.
120146pub ( super ) fn install ( ) {
121147 unsafe {
122148 let alt_stack_size: usize = min_sigstack_size ( ) + 64 * 1024 ;
@@ -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