@@ -67,7 +67,7 @@ macro_rules! rtunwrap {
6767 } ;
6868}
6969
70- fn handle_rt_panic ( e : Box < dyn Any + Send > ) {
70+ fn handle_rt_panic < T > ( e : Box < dyn Any + Send > ) -> T {
7171 mem:: forget ( e) ;
7272 rtabort ! ( "initialization or cleanup bug" ) ;
7373}
@@ -157,7 +157,7 @@ fn lang_start_internal(
157157 argc : isize ,
158158 argv : * const * const u8 ,
159159 sigpipe : u8 ,
160- ) -> Result < isize , ! > {
160+ ) -> isize {
161161 // Guard against the code called by this function from unwinding outside of the Rust-controlled
162162 // code, which is UB. This is a requirement imposed by a combination of how the
163163 // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
@@ -168,19 +168,33 @@ fn lang_start_internal(
168168 // panic is a std implementation bug. A quite likely one too, as there isn't any way to
169169 // prevent std from accidentally introducing a panic to these functions. Another is from
170170 // 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
178187 } ) ;
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)
184198}
185199
186200#[ cfg( not( any( test, doctest) ) ) ]
@@ -191,11 +205,10 @@ fn lang_start<T: crate::process::Termination + 'static>(
191205 argv : * const * const u8 ,
192206 sigpipe : u8 ,
193207) -> isize {
194- let Ok ( v ) = lang_start_internal (
208+ lang_start_internal (
195209 & move || crate :: sys:: backtrace:: __rust_begin_short_backtrace ( main) . report ( ) . to_i32 ( ) ,
196210 argc,
197211 argv,
198212 sigpipe,
199- ) ;
200- v
213+ )
201214}
0 commit comments