Skip to content

Commit 6f35373

Browse files
committed
std: use less catch_unwind in lang_start_internal
1 parent ac4379f commit 6f35373

File tree

1 file changed

+40
-16
lines changed

1 file changed

+40
-16
lines changed

library/std/src/rt.rs

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,30 @@ fn lang_start_internal(
127127
argc: isize,
128128
argv: *const *const u8,
129129
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+
136154
// Guard against the code called by this function from unwinding outside of the Rust-controlled
137155
// code, which is UB. This is a requirement imposed by a combination of how the
138156
// `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
@@ -143,14 +161,21 @@ fn lang_start_internal(
143161
// panic is a std implementation bug. A quite likely one too, as there isn't any way to
144162
// prevent std from accidentally introducing a panic to these functions. Another is from
145163
// user code from `main` or, more nefariously, as described in e.g. issue #86030.
164+
let mut guard = PanicGuard { reason: AbortReason::Init };
165+
146166
// 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);
154179
ret_code
155180
}
156181

@@ -162,11 +187,10 @@ fn lang_start<T: crate::process::Termination + 'static>(
162187
argv: *const *const u8,
163188
sigpipe: u8,
164189
) -> isize {
165-
let Ok(v) = lang_start_internal(
190+
lang_start_internal(
166191
&move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
167192
argc,
168193
argv,
169194
sigpipe,
170-
);
171-
v
195+
)
172196
}

0 commit comments

Comments
 (0)