@@ -127,12 +127,30 @@ fn lang_start_internal(
127
127
argc : isize ,
128
128
argv : * const * const u8 ,
129
129
sigpipe : u8 ,
130
- ) -> Result < isize , !> {
131
- use crate :: { mem, panic} ;
132
- let rt_abort = move |e| {
133
- mem:: forget ( e) ;
134
- rtabort ! ( "initialization or cleanup bug" ) ;
135
- } ;
130
+ ) -> isize {
131
+ enum AbortReason {
132
+ Init ,
133
+ PayloadDrop ,
134
+ Cleanup ,
135
+ }
136
+
137
+ struct PanicGuard {
138
+ reason : AbortReason ,
139
+ }
140
+
141
+ impl Drop for PanicGuard {
142
+ fn drop ( & mut self ) {
143
+ rtprintpanic ! (
144
+ "{}" ,
145
+ match self . reason {
146
+ AbortReason :: Init => "rt::init should not unwind" ,
147
+ AbortReason :: PayloadDrop => "drop of the panic payload panicked" ,
148
+ AbortReason :: Cleanup => "rt::cleanup should not unwind" ,
149
+ }
150
+ ) ;
151
+ }
152
+ }
153
+
136
154
// Guard against the code called by this function from unwinding outside of the Rust-controlled
137
155
// code, which is UB. This is a requirement imposed by a combination of how the
138
156
// `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
@@ -143,14 +161,21 @@ fn lang_start_internal(
143
161
// panic is a std implementation bug. A quite likely one too, as there isn't any way to
144
162
// prevent std from accidentally introducing a panic to these functions. Another is from
145
163
// user code from `main` or, more nefariously, as described in e.g. issue #86030.
164
+ let mut guard = PanicGuard { reason : AbortReason :: Init } ;
165
+
146
166
// SAFETY: Only called once during runtime initialization.
147
- panic:: catch_unwind ( move || unsafe { init ( argc, argv, sigpipe) } ) . map_err ( rt_abort) ?;
148
- let ret_code = panic:: catch_unwind ( move || panic:: catch_unwind ( main) . unwrap_or ( 101 ) as isize )
149
- . map_err ( move |e| {
150
- mem:: forget ( e) ;
151
- rtabort ! ( "drop of the panic payload panicked" ) ;
152
- } ) ;
153
- panic:: catch_unwind ( cleanup) . map_err ( rt_abort) ?;
167
+ unsafe {
168
+ init ( argc, argv, sigpipe) ;
169
+ }
170
+
171
+ guard. reason = AbortReason :: PayloadDrop ;
172
+ let ret_code = crate :: panic:: catch_unwind ( main) . unwrap_or ( 101 ) as isize ;
173
+
174
+ guard. reason = AbortReason :: Cleanup ;
175
+ cleanup ( ) ;
176
+
177
+ // No panic occurred, so do not abort.
178
+ crate :: mem:: forget ( guard) ;
154
179
ret_code
155
180
}
156
181
@@ -162,11 +187,10 @@ fn lang_start<T: crate::process::Termination + 'static>(
162
187
argv : * const * const u8 ,
163
188
sigpipe : u8 ,
164
189
) -> isize {
165
- let Ok ( v ) = lang_start_internal (
190
+ lang_start_internal (
166
191
& move || crate :: sys_common:: backtrace:: __rust_begin_short_backtrace ( main) . report ( ) . to_i32 ( ) ,
167
192
argc,
168
193
argv,
169
194
sigpipe,
170
- ) ;
171
- v
195
+ )
172
196
}
0 commit comments