Prevent __rust_begin_short_backtrace
frames from being tail-call optimised away
This commit is contained in:
parent
4d4342347b
commit
5792840bf5
6 changed files with 74 additions and 12 deletions
|
@ -434,7 +434,9 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
|
||||||
|
|
||||||
let loc = info.location().unwrap(); // The current implementation always returns Some
|
let loc = info.location().unwrap(); // The current implementation always returns Some
|
||||||
let msg = info.message().unwrap(); // The current implementation always returns Some
|
let msg = info.message().unwrap(); // The current implementation always returns Some
|
||||||
rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc);
|
crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
|
||||||
|
rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the entry point of panicking for the non-format-string variants of
|
/// This is the entry point of panicking for the non-format-string variants of
|
||||||
|
@ -453,7 +455,10 @@ pub fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
||||||
intrinsics::abort()
|
intrinsics::abort()
|
||||||
}
|
}
|
||||||
|
|
||||||
rust_panic_with_hook(&mut PanicPayload::new(msg), None, Location::caller());
|
let loc = Location::caller();
|
||||||
|
return crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
|
||||||
|
rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc)
|
||||||
|
});
|
||||||
|
|
||||||
struct PanicPayload<A> {
|
struct PanicPayload<A> {
|
||||||
inner: Option<A>,
|
inner: Option<A>,
|
||||||
|
|
|
@ -48,9 +48,7 @@ fn lang_start_internal(
|
||||||
sys::args::init(argc, argv);
|
sys::args::init(argc, argv);
|
||||||
|
|
||||||
// Let's run some code!
|
// Let's run some code!
|
||||||
let exit_code = panic::catch_unwind(|| {
|
let exit_code = panic::catch_unwind(main);
|
||||||
sys_common::backtrace::__rust_begin_short_backtrace(move || main())
|
|
||||||
});
|
|
||||||
|
|
||||||
sys_common::cleanup();
|
sys_common::cleanup();
|
||||||
exit_code.unwrap_or(101) as isize
|
exit_code.unwrap_or(101) as isize
|
||||||
|
@ -64,5 +62,9 @@ fn lang_start<T: crate::process::Termination + 'static>(
|
||||||
argc: isize,
|
argc: isize,
|
||||||
argv: *const *const u8,
|
argv: *const *const u8,
|
||||||
) -> isize {
|
) -> isize {
|
||||||
lang_start_internal(&move || main().report(), argc, argv)
|
lang_start_internal(
|
||||||
|
&move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report(),
|
||||||
|
argc,
|
||||||
|
argv,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,8 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
|
||||||
bt_fmt.add_context()?;
|
bt_fmt.add_context()?;
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
let mut res = Ok(());
|
let mut res = Ok(());
|
||||||
|
// Start immediately if we're not using a short backtrace.
|
||||||
|
let mut start = print_fmt != PrintFmt::Short;
|
||||||
backtrace_rs::trace_unsynchronized(|frame| {
|
backtrace_rs::trace_unsynchronized(|frame| {
|
||||||
if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
|
if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
|
||||||
return false;
|
return false;
|
||||||
|
@ -89,16 +91,24 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
|
||||||
stop = true;
|
stop = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if sym.contains("__rust_end_short_backtrace") {
|
||||||
|
start = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = bt_fmt.frame().symbol(frame, symbol);
|
if start {
|
||||||
|
res = bt_fmt.frame().symbol(frame, symbol);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if stop {
|
if stop {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if !hit {
|
if !hit {
|
||||||
res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
|
if start {
|
||||||
|
res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idx += 1;
|
idx += 1;
|
||||||
|
@ -123,10 +133,29 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
|
||||||
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
|
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
|
||||||
where
|
where
|
||||||
F: FnOnce() -> T,
|
F: FnOnce() -> T,
|
||||||
F: Send,
|
|
||||||
T: Send,
|
|
||||||
{
|
{
|
||||||
f()
|
let result = f();
|
||||||
|
|
||||||
|
// prevent this frame from being tail-call optimised away
|
||||||
|
crate::hint::black_box(());
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
|
||||||
|
/// this is only inline(never) when backtraces in libstd are enabled, otherwise
|
||||||
|
/// it's fine to optimize away.
|
||||||
|
#[cfg_attr(feature = "backtrace", inline(never))]
|
||||||
|
pub fn __rust_end_short_backtrace<F, T>(f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce() -> T,
|
||||||
|
{
|
||||||
|
let result = f();
|
||||||
|
|
||||||
|
// prevent this frame from being tail-call optimised away
|
||||||
|
crate::hint::black_box(());
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RustBacktrace {
|
pub enum RustBacktrace {
|
||||||
|
|
|
@ -514,7 +514,10 @@ pub fn run_test(
|
||||||
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
|
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
|
fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
|
||||||
f()
|
f();
|
||||||
|
|
||||||
|
// prevent this frame from being tail-call optimised away
|
||||||
|
black_box(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_test_in_process(
|
fn run_test_in_process(
|
||||||
|
|
18
src/test/ui/panics/issue-47429-short-backtraces.rs
Normal file
18
src/test/ui/panics/issue-47429-short-backtraces.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Regression test for #47429: short backtraces were not terminating correctly
|
||||||
|
|
||||||
|
// compile-flags: -O
|
||||||
|
// run-fail
|
||||||
|
// check-run-results
|
||||||
|
// exec-env:RUST_BACKTRACE=1
|
||||||
|
|
||||||
|
// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
|
||||||
|
// ignore-android FIXME #17520
|
||||||
|
// ignore-cloudabi spawning processes is not supported
|
||||||
|
// ignore-openbsd no support for libbacktrace without filename
|
||||||
|
// ignore-wasm no panic or subprocess support
|
||||||
|
// ignore-emscripten no panic or subprocess support
|
||||||
|
// ignore-sgx no subprocess support
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
panic!()
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:17:5
|
||||||
|
stack backtrace:
|
||||||
|
0: std::panicking::begin_panic
|
||||||
|
1: issue_47429_short_backtraces::main
|
||||||
|
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
|
Loading…
Add table
Add a link
Reference in a new issue