Skip to content

Commit ca8b754

Browse files
committed
Don't show the std frames before user code on unwinding.
When `RUST_BACKTRACE=1`, remove all frames after `__rust_maybe_catch_panic`. Tested on `main`, threads, tests and benches. Cleaning of the top of the stacktrace is let to a future PR. Fixes #40201 See #41815
1 parent f3fc547 commit ca8b754

File tree

4 files changed

+68
-13
lines changed

4 files changed

+68
-13
lines changed

src/libstd/rt.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
2929

3030
#[cfg(not(test))]
3131
#[lang = "start"]
32-
fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
33-
use mem;
32+
fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize {
3433
use panic;
3534
use sys;
3635
use sys_common;
@@ -54,7 +53,9 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
5453
sys::args::init(argc, argv);
5554

5655
// Let's run some code!
57-
let res = panic::catch_unwind(mem::transmute::<_, fn()>(main));
56+
let res = panic::catch_unwind(|| {
57+
::sys_common::backtrace::__rust_begin_short_backtrace(main)
58+
});
5859
sys_common::cleanup();
5960
res.is_err()
6061
};

src/libstd/sys_common/backtrace.rs

+40-4
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,47 @@ fn _print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
9393
Ok(())
9494
}
9595

96-
fn filter_frames(_frames: &[Frame],
97-
_format: PrintFormat,
98-
_context: &BacktraceContext) -> (usize, usize)
96+
/// Returns a number of frames to remove at the beginning and at the end of the
97+
/// backtrace, according to the backtrace format.
98+
fn filter_frames(frames: &[Frame],
99+
format: PrintFormat,
100+
context: &BacktraceContext) -> (usize, usize)
99101
{
100-
(0, 0)
102+
if format == PrintFormat::Full {
103+
return (0, 0);
104+
}
105+
106+
let skipped_before = 0;
107+
108+
let skipped_after = frames.len() - frames.iter().position(|frame| {
109+
let mut is_marker = false;
110+
let _ = resolve_symname(*frame, |symname| {
111+
if let Some(mangled_symbol_name) = symname {
112+
// Use grep to find the concerned functions
113+
if mangled_symbol_name.contains("__rust_begin_short_backtrace") {
114+
is_marker = true;
115+
}
116+
}
117+
Ok(())
118+
}, context);
119+
is_marker
120+
}).unwrap_or(frames.len());
121+
122+
if skipped_before + skipped_after >= frames.len() {
123+
// Avoid showing completely empty backtraces
124+
return (0, 0);
125+
}
126+
127+
(skipped_before, skipped_after)
128+
}
129+
130+
131+
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
132+
#[inline(never)]
133+
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
134+
where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
135+
{
136+
f()
101137
}
102138

103139
/// Controls how the backtrace should be formated.

src/libstd/thread/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,9 @@ impl Builder {
358358
}
359359
unsafe {
360360
thread_info::set(imp::guard::current(), their_thread);
361-
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f));
361+
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
362+
::sys_common::backtrace::__rust_begin_short_backtrace(f)
363+
}));
362364
*their_packet.get() = Some(try_result);
363365
}
364366
};

src/libtest/lib.rs

+21-5
Original file line numberDiff line numberDiff line change
@@ -1314,12 +1314,16 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd
13141314
let testfn = match x.testfn {
13151315
DynBenchFn(bench) => {
13161316
DynTestFn(Box::new(move |()| {
1317-
bench::run_once(|b| bench.run(b))
1317+
bench::run_once(|b| {
1318+
__rust_begin_short_backtrace(|| bench.run(b))
1319+
})
13181320
}))
13191321
}
13201322
StaticBenchFn(benchfn) => {
13211323
DynTestFn(Box::new(move |()| {
1322-
bench::run_once(|b| benchfn(b))
1324+
bench::run_once(|b| {
1325+
__rust_begin_short_backtrace(|| benchfn(b))
1326+
})
13231327
}))
13241328
}
13251329
f => f,
@@ -1425,12 +1429,24 @@ pub fn run_test(opts: &TestOpts,
14251429
monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap();
14261430
return;
14271431
}
1428-
DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
1429-
StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture,
1430-
Box::new(move |()| f())),
1432+
DynTestFn(f) => {
1433+
let cb = move |()| {
1434+
__rust_begin_short_backtrace(|| f.call_box(()))
1435+
};
1436+
run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb))
1437+
}
1438+
StaticTestFn(f) =>
1439+
run_test_inner(desc, monitor_ch, opts.nocapture,
1440+
Box::new(move |()| __rust_begin_short_backtrace(f))),
14311441
}
14321442
}
14331443

1444+
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
1445+
#[inline(never)]
1446+
fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
1447+
f()
1448+
}
1449+
14341450
fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any + Send>>) -> TestResult {
14351451
match (&desc.should_panic, task_result) {
14361452
(&ShouldPanic::No, Ok(())) |

0 commit comments

Comments
 (0)