Skip to content

Commit e491cae

Browse files
committed
Auto merge of rust-lang#135359 - RalfJung:lang-start-unwind, r=joboet
use a single large catch_unwind in lang_start I originally planned to use `abort_unwind` but reading the comment in `thread_cleanup` it seems we are deliberately going for slightly nicer error messages here, so this preserves that. It still seems nice to not repeat `catch_unwind` so often.
2 parents 35c2908 + 471d830 commit e491cae

File tree

5 files changed

+36
-23
lines changed

5 files changed

+36
-23
lines changed

library/std/src/rt.rs

+30-17
Original file line numberDiff line numberDiff line change
@@ -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
}

src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
1515
= note: inside `std::panicking::r#try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at RUSTLIB/std/src/panicking.rs:LL:CC
1616
= note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at RUSTLIB/std/src/panic.rs:LL:CC
1717
= note: inside closure at RUSTLIB/std/src/rt.rs:LL:CC
18-
= note: inside `std::panicking::r#try::do_call::<{closure@std::rt::lang_start_internal::{closure#1}}, isize>` at RUSTLIB/std/src/panicking.rs:LL:CC
19-
= note: inside `std::panicking::r#try::<isize, {closure@std::rt::lang_start_internal::{closure#1}}>` at RUSTLIB/std/src/panicking.rs:LL:CC
20-
= note: inside `std::panic::catch_unwind::<{closure@std::rt::lang_start_internal::{closure#1}}, isize>` at RUSTLIB/std/src/panic.rs:LL:CC
18+
= note: inside `std::panicking::r#try::do_call::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panicking.rs:LL:CC
19+
= note: inside `std::panicking::r#try::<isize, {closure@std::rt::lang_start_internal::{closure#0}}>` at RUSTLIB/std/src/panicking.rs:LL:CC
20+
= note: inside `std::panic::catch_unwind::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panic.rs:LL:CC
2121
= note: inside `std::rt::lang_start_internal` at RUSTLIB/std/src/rt.rs:LL:CC
2222
= note: inside `std::rt::lang_start::<()>` at RUSTLIB/std/src/rt.rs:LL:CC
2323

src/tools/miri/tests/pass/backtrace/backtrace-api-v1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ RUSTLIB/core/src/ops/function.rs:LL:CC (std::ops::function::impls::call_once)
1010
RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call)
1111
RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try)
1212
RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind)
13-
RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal::{closure#1})
13+
RUSTLIB/std/src/rt.rs:LL:CC (std::rt::lang_start_internal::{closure#0})
1414
RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try::do_call)
1515
RUSTLIB/std/src/panicking.rs:LL:CC (std::panicking::r#try)
1616
RUSTLIB/std/src/panic.rs:LL:CC (std::panic::catch_unwind)

src/tools/miri/tests/pass/backtrace/backtrace-global-alloc.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
at RUSTLIB/std/src/panicking.rs:LL:CC
1515
7: std::panic::catch_unwind
1616
at RUSTLIB/std/src/panic.rs:LL:CC
17-
8: std::rt::lang_start_internal::{closure#1}
17+
8: std::rt::lang_start_internal::{closure#0}
1818
at RUSTLIB/std/src/rt.rs:LL:CC
1919
9: std::panicking::r#try::do_call
2020
at RUSTLIB/std/src/panicking.rs:LL:CC

src/tools/miri/tests/pass/backtrace/backtrace-std.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
at RUSTLIB/std/src/panicking.rs:LL:CC
2323
11: std::panic::catch_unwind
2424
at RUSTLIB/std/src/panic.rs:LL:CC
25-
12: std::rt::lang_start_internal::{closure#1}
25+
12: std::rt::lang_start_internal::{closure#0}
2626
at RUSTLIB/std/src/rt.rs:LL:CC
2727
13: std::panicking::r#try::do_call
2828
at RUSTLIB/std/src/panicking.rs:LL:CC

0 commit comments

Comments
 (0)