diff options
| author | Alan Egerton <eggyal@gmail.com> | 2020-08-04 22:18:20 +0100 |
|---|---|---|
| committer | Alan Egerton <eggyal@gmail.com> | 2020-08-07 19:31:25 +0100 |
| commit | 5792840bf52e4cf77ebb7b3bd93e9c90dd23f4e7 (patch) | |
| tree | a3bfeaade21999a1b1bba131225ba0238e767d19 /library/std/src/sys_common | |
| parent | 4d4342347b71313258a46e506ee0a258f365185c (diff) | |
| download | rust-5792840bf52e4cf77ebb7b3bd93e9c90dd23f4e7.tar.gz rust-5792840bf52e4cf77ebb7b3bd93e9c90dd23f4e7.zip | |
Prevent `__rust_begin_short_backtrace` frames from being tail-call optimised away
Diffstat (limited to 'library/std/src/sys_common')
| -rw-r--r-- | library/std/src/sys_common/backtrace.rs | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index d386a656e4f..1c5fbf7d701 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -74,6 +74,8 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: bt_fmt.add_context()?; let mut idx = 0; 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| { if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { return false; @@ -89,16 +91,24 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: stop = true; 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 { return false; } 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; @@ -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 where 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 { |
