@@ -67,7 +67,7 @@ macro_rules! rtunwrap {
67
67
} ;
68
68
}
69
69
70
- fn handle_rt_panic ( e : Box < dyn Any + Send > ) {
70
+ fn handle_rt_panic < T > ( e : Box < dyn Any + Send > ) -> T {
71
71
mem:: forget ( e) ;
72
72
rtabort ! ( "initialization or cleanup bug" ) ;
73
73
}
@@ -157,7 +157,7 @@ fn lang_start_internal(
157
157
argc : isize ,
158
158
argv : * const * const u8 ,
159
159
sigpipe : u8 ,
160
- ) -> Result < isize , ! > {
160
+ ) -> isize {
161
161
// Guard against the code called by this function from unwinding outside of the Rust-controlled
162
162
// code, which is UB. This is a requirement imposed by a combination of how the
163
163
// `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
@@ -168,19 +168,33 @@ fn lang_start_internal(
168
168
// panic is a std implementation bug. A quite likely one too, as there isn't any way to
169
169
// prevent std from accidentally introducing a panic to these functions. Another is from
170
170
// user code from `main` or, more nefariously, as described in e.g. issue #86030.
171
- // SAFETY: Only called once during runtime initialization.
172
- panic:: catch_unwind ( move || unsafe { init ( argc, argv, sigpipe) } )
173
- . unwrap_or_else ( handle_rt_panic) ;
174
- let ret_code = panic:: catch_unwind ( move || panic:: catch_unwind ( main) . unwrap_or ( 101 ) as isize )
175
- . map_err ( move |e| {
176
- mem:: forget ( e) ;
177
- rtabort ! ( "drop of the panic payload panicked" ) ;
171
+ //
172
+ // We use `catch_unwind` with `handle_rt_panic` instead of `abort_unwind` to make the error in
173
+ // case of a panic a bit nicer.
174
+ panic:: catch_unwind ( move || {
175
+ // SAFETY: Only called once during runtime initialization.
176
+ unsafe { init ( argc, argv, sigpipe) } ;
177
+
178
+ let ret_code = panic:: catch_unwind ( main) . unwrap_or_else ( move |payload| {
179
+ // Carefully dispose of the panic payload.
180
+ let payload = panic:: AssertUnwindSafe ( payload) ;
181
+ panic:: catch_unwind ( move || drop ( { payload } . 0 ) ) . unwrap_or_else ( move |e| {
182
+ mem:: forget ( e) ; // do *not* drop the 2nd payload
183
+ rtabort ! ( "drop of the panic payload panicked" ) ;
184
+ } ) ;
185
+ // Return error code for panicking programs.
186
+ 101
178
187
} ) ;
179
- panic:: catch_unwind ( cleanup) . unwrap_or_else ( handle_rt_panic) ;
180
- // Guard against multiple threads calling `libc::exit` concurrently.
181
- // See the documentation for `unique_thread_exit` for more information.
182
- panic:: catch_unwind ( crate :: sys:: exit_guard:: unique_thread_exit) . unwrap_or_else ( handle_rt_panic) ;
183
- ret_code
188
+ let ret_code = ret_code as isize ;
189
+
190
+ cleanup ( ) ;
191
+ // Guard against multiple threads calling `libc::exit` concurrently.
192
+ // See the documentation for `unique_thread_exit` for more information.
193
+ crate :: sys:: exit_guard:: unique_thread_exit ( ) ;
194
+
195
+ ret_code
196
+ } )
197
+ . unwrap_or_else ( handle_rt_panic)
184
198
}
185
199
186
200
#[ cfg( not( any( test, doctest) ) ) ]
@@ -191,11 +205,10 @@ fn lang_start<T: crate::process::Termination + 'static>(
191
205
argv : * const * const u8 ,
192
206
sigpipe : u8 ,
193
207
) -> isize {
194
- let Ok ( v ) = lang_start_internal (
208
+ lang_start_internal (
195
209
& move || crate :: sys:: backtrace:: __rust_begin_short_backtrace ( main) . report ( ) . to_i32 ( ) ,
196
210
argc,
197
211
argv,
198
212
sigpipe,
199
- ) ;
200
- v
213
+ )
201
214
}
0 commit comments