@@ -6,6 +6,15 @@ use std::{fmt, mem, ptr, slice};
6
6
7
7
use rustc_interface:: util:: { DEFAULT_STACK_SIZE , STACK_SIZE } ;
8
8
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
+
9
18
unsafe extern "C" {
10
19
fn backtrace_symbols_fd ( buffer : * const * mut libc:: c_void , size : libc:: c_int , fd : libc:: c_int ) ;
11
20
}
@@ -39,8 +48,19 @@ macro raw_errln($tokens:tt) {
39
48
/// # Safety
40
49
///
41
50
/// 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 ) {
43
52
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
+
44
64
let stack = unsafe {
45
65
// Reserve data segment so we don't have to malloc in a signal handler, which might fail
46
66
// 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) {
54
74
} ;
55
75
56
76
// 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
+
58
79
let mut written = 1 ;
59
80
let mut consumed = 0 ;
60
81
// 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) {
94
115
written += rem. len ( ) + 1 ;
95
116
96
117
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 {
98
119
// technically speculation, but assert it with confidence anyway.
99
120
// rustc only arrived in this signal handler because bad things happened
100
121
// 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) {
106
127
written += 1 ;
107
128
}
108
129
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
+ }
113
139
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" ) ;
116
142
} ;
117
143
}
118
144
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.
120
146
pub ( super ) fn install ( ) {
121
147
unsafe {
122
148
let alt_stack_size: usize = min_sigstack_size ( ) + 64 * 1024 ;
@@ -129,7 +155,9 @@ pub(super) fn install() {
129
155
sa. sa_sigaction = print_stack_trace as libc:: sighandler_t ;
130
156
sa. sa_flags = libc:: SA_NODEFER | libc:: SA_RESETHAND | libc:: SA_ONSTACK ;
131
157
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
+ }
133
161
}
134
162
}
135
163
0 commit comments