From 680e2b7290e359bc47a0e731140fd6860acd03c1 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Sat, 4 Mar 2017 10:27:52 -0500 Subject: [PATCH 01/17] Ignore more frames on backtrace unwinding. Correctly handles panics in threads and tests. First, the frames after `__rust_maybe_catch_panic` are discarded, then it uses a blacklist that does some more fine-tuning. Since frames after the call to `__rust_maybe_catch_panic` seem to be platform-independant, `BAD_PREFIXES_BOTTOM` could probably be cleaned a bit. Fixes #40201 --- src/libstd/sys_common/backtrace.rs | 33 +++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 99297b781e443..08cfa4634819c 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -148,6 +148,21 @@ fn filter_frames(frames: &[Frame], "__scrt_common_main_seh", "_ZN4drop", "mingw_set_invalid_parameter_handler", + "_ZN4core3ops6FnOnce9call_once", + "ZN4core3ops6FnOnce9call_once", + "core::ops::FnOnce::call_once", + + // tests + "_ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce$LT$$LP$$RP$$GT$$GT$9call_once", + "ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce$LT$$LP$$RP$$GT$$GT$9call_once", + " as core::ops::FnOnce<()>>::call_once", + "_ZN4test8run_test", + "ZN4test8run_test", + "test::run_test", + "_ZN42_$LT$F$u20$as$u20$test..FnBox$LT$T$GT$$GT$8call_box", + "ZN42_$LT$F$u20$as$u20$test..FnBox$LT$T$GT$$GT$8call_box", + ">::call_box", + ]; let is_good_frame = |frame: Frame, bad_prefixes: &[&str]| { @@ -164,11 +179,23 @@ fn filter_frames(frames: &[Frame], let skipped_before = frames.iter().position(|frame| { is_good_frame(*frame, BAD_PREFIXES_TOP) }).unwrap_or(frames.len()); - let skipped_after = frames[skipped_before..].iter().rev().position(|frame| { + let idx_catch_panic = skipped_before + frames[skipped_before..].iter().position(|frame| { + let mut is_rmcp = false; + let _ = resolve_symname(*frame, |symname| { + if let Some(mangled_symbol_name) = symname { + if mangled_symbol_name == "__rust_maybe_catch_panic" { + is_rmcp = true; + } + } + Ok(()) + }, context); + is_rmcp + }).unwrap_or(0); + let skipped_after = frames.len() - idx_catch_panic + frames[skipped_before..idx_catch_panic].iter().rev().position(|frame| { is_good_frame(*frame, BAD_PREFIXES_BOTTOM) - }).unwrap_or(frames.len() - skipped_before); + }).unwrap_or(0); - if skipped_before + skipped_after == frames.len() { + if skipped_before + skipped_after >= frames.len() { // Avoid showing completely empty backtraces return (0, 0); } From 2183ef68ecd44edca722b9c247df398a221026fd Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Sat, 4 Mar 2017 13:34:05 -0500 Subject: [PATCH 02/17] Remove unneeded blacklisted functions --- src/libstd/sys_common/backtrace.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 08cfa4634819c..067cfdcfeb59d 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -107,47 +107,47 @@ fn filter_frames(frames: &[Frame], "_ZN3std3sys3imp9backtrace", "ZN3std3sys3imp9backtrace", "std::sys::imp::backtrace", + "_ZN3std10sys_common9backtrace", "ZN3std10sys_common9backtrace", "std::sys_common::backtrace", + "_ZN3std9panicking", "ZN3std9panicking", "std::panicking", + "_ZN4core9panicking", "ZN4core9panicking", "core::panicking", + "_ZN4core6result13unwrap_failed", "ZN4core6result13unwrap_failed", "core::result::unwrap_failed", + "rust_begin_unwind", "_ZN4drop", "mingw_set_invalid_parameter_handler", ]; static BAD_PREFIXES_BOTTOM: &'static [&'static str] = &[ + "_ZN4core9panicking", + "ZN4core9panicking", + "core::panicking", + "_ZN3std9panicking", "ZN3std9panicking", "std::panicking", + "_ZN3std5panic", "ZN3std5panic", "std::panic", - "_ZN4core9panicking", - "ZN4core9panicking", - "core::panicking", - "_ZN3std2rt10lang_start", - "ZN3std2rt10lang_start", - "std::rt::lang_start", - "panic_unwind::__rust_maybe_catch_panic", - "__rust_maybe_catch_panic", - "_rust_maybe_catch_panic", - "__libc_start_main", + "__rust_try", - "_start", - "main", "BaseThreadInitThunk", "RtlInitializeExceptionChain", "__scrt_common_main_seh", "_ZN4drop", "mingw_set_invalid_parameter_handler", + "_ZN4core3ops6FnOnce9call_once", "ZN4core3ops6FnOnce9call_once", "core::ops::FnOnce::call_once", @@ -156,9 +156,11 @@ fn filter_frames(frames: &[Frame], "_ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce$LT$$LP$$RP$$GT$$GT$9call_once", "ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce$LT$$LP$$RP$$GT$$GT$9call_once", " as core::ops::FnOnce<()>>::call_once", + "_ZN4test8run_test", "ZN4test8run_test", "test::run_test", + "_ZN42_$LT$F$u20$as$u20$test..FnBox$LT$T$GT$$GT$8call_box", "ZN42_$LT$F$u20$as$u20$test..FnBox$LT$T$GT$$GT$8call_box", ">::call_box", From dfaed07240298b497372f46c5a1eecf65976c795 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Sat, 4 Mar 2017 13:59:28 -0500 Subject: [PATCH 03/17] Fix long lines --- src/libstd/sys_common/backtrace.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 067cfdcfeb59d..fdaba3640b718 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -153,8 +153,10 @@ fn filter_frames(frames: &[Frame], "core::ops::FnOnce::call_once", // tests - "_ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce$LT$$LP$$RP$$GT$$GT$9call_once", - "ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce$LT$$LP$$RP$$GT$$GT$9call_once", + "_ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce\ + $LT$$LP$$RP$$GT$$GT$9call_once", + "ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce\ + $LT$$LP$$RP$$GT$$GT$9call_once", " as core::ops::FnOnce<()>>::call_once", "_ZN4test8run_test", @@ -193,7 +195,11 @@ fn filter_frames(frames: &[Frame], }, context); is_rmcp }).unwrap_or(0); - let skipped_after = frames.len() - idx_catch_panic + frames[skipped_before..idx_catch_panic].iter().rev().position(|frame| { + let skipped_after = + frames.len() - idx_catch_panic + + frames[skipped_before..idx_catch_panic].iter() + .rev() + .position(|frame| { is_good_frame(*frame, BAD_PREFIXES_BOTTOM) }).unwrap_or(0); From c40ea765d6dafe5c7d8d41e73d7cdec6d74566f2 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Sat, 4 Mar 2017 14:13:58 -0500 Subject: [PATCH 04/17] Handle panic::catch_unwind. --- src/libstd/sys_common/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index fdaba3640b718..3604c9b00b3bc 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -183,7 +183,7 @@ fn filter_frames(frames: &[Frame], let skipped_before = frames.iter().position(|frame| { is_good_frame(*frame, BAD_PREFIXES_TOP) }).unwrap_or(frames.len()); - let idx_catch_panic = skipped_before + frames[skipped_before..].iter().position(|frame| { + let idx_catch_panic = skipped_before + frames[skipped_before..].iter().rposition(|frame| { let mut is_rmcp = false; let _ = resolve_symname(*frame, |symname| { if let Some(mangled_symbol_name) = symname { From 33e42a35964aa1a334e40f3bc50d8ba336f51d49 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Sat, 4 Mar 2017 14:32:44 -0500 Subject: [PATCH 05/17] Support of _rust... and panic_unwind::__rust... --- src/libstd/sys_common/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 3604c9b00b3bc..a83ca4e72aad6 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -187,7 +187,7 @@ fn filter_frames(frames: &[Frame], let mut is_rmcp = false; let _ = resolve_symname(*frame, |symname| { if let Some(mangled_symbol_name) = symname { - if mangled_symbol_name == "__rust_maybe_catch_panic" { + if mangled_symbol_name.contains("rust_maybe_catch_panic") { is_rmcp = true; } } From d54caabeeed078cb8dc38d136685dcc012acccef Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Sat, 4 Mar 2017 15:16:51 -0500 Subject: [PATCH 06/17] Fix index calculation --- src/libstd/sys_common/backtrace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index a83ca4e72aad6..7b90275713718 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -183,7 +183,7 @@ fn filter_frames(frames: &[Frame], let skipped_before = frames.iter().position(|frame| { is_good_frame(*frame, BAD_PREFIXES_TOP) }).unwrap_or(frames.len()); - let idx_catch_panic = skipped_before + frames[skipped_before..].iter().rposition(|frame| { + let idx_catch_panic = frames.iter().rposition(|frame| { let mut is_rmcp = false; let _ = resolve_symname(*frame, |symname| { if let Some(mangled_symbol_name) = symname { @@ -194,7 +194,7 @@ fn filter_frames(frames: &[Frame], Ok(()) }, context); is_rmcp - }).unwrap_or(0); + }).unwrap_or(frames.len()); let skipped_after = frames.len() - idx_catch_panic + frames[skipped_before..idx_catch_panic].iter() From 3353a42f1424f445c80ecbbc3b12f20003786599 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Sat, 4 Mar 2017 15:17:22 -0500 Subject: [PATCH 07/17] Hide backtrace when RUST_BACKTRACE is empty --- src/libstd/sys_common/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 7b90275713718..af43bd21e5651 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -233,7 +233,7 @@ pub fn log_enabled() -> Option { } let val = match env::var_os("RUST_BACKTRACE") { - Some(x) => if &x == "0" { + Some(x) => if &x == "0" || &x == "" { None } else if &x == "full" { Some(PrintFormat::Full) From deeaa73a1831e99fb15ee74cbbf2641af4907cdd Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Fri, 17 Mar 2017 12:33:14 -0400 Subject: [PATCH 08/17] [backtrace] Remove dupplicated checks --- src/libstd/sys_common/backtrace.rs | 53 +++++++++--------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index af43bd21e5651..f70bf60aa8e47 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -104,42 +104,30 @@ fn filter_frames(frames: &[Frame], // We want to filter out frames with some prefixes // from both top and bottom of the call stack. static BAD_PREFIXES_TOP: &'static [&'static str] = &[ - "_ZN3std3sys3imp9backtrace", + // std::sys::imp::backtrace "ZN3std3sys3imp9backtrace", - "std::sys::imp::backtrace", - - "_ZN3std10sys_common9backtrace", + // std::sys_common::backtrace "ZN3std10sys_common9backtrace", - "std::sys_common::backtrace", - - "_ZN3std9panicking", + // std::panicking "ZN3std9panicking", - "std::panicking", - - "_ZN4core9panicking", + // core::panicking "ZN4core9panicking", - "core::panicking", - - "_ZN4core6result13unwrap_failed", + // core::result::unwrap_failed "ZN4core6result13unwrap_failed", - "core::result::unwrap_failed", "rust_begin_unwind", "_ZN4drop", "mingw_set_invalid_parameter_handler", ]; static BAD_PREFIXES_BOTTOM: &'static [&'static str] = &[ - "_ZN4core9panicking", + // core::panicking "ZN4core9panicking", - "core::panicking", - - "_ZN3std9panicking", + // std::panicking "ZN3std9panicking", - "std::panicking", - - "_ZN3std5panic", + // std::panic "ZN3std5panic", - "std::panic", + // core::ops::FnOnce::call_once + "ZN4core3ops6FnOnce9call_once", "__rust_try", "BaseThreadInitThunk", @@ -148,31 +136,20 @@ fn filter_frames(frames: &[Frame], "_ZN4drop", "mingw_set_invalid_parameter_handler", - "_ZN4core3ops6FnOnce9call_once", - "ZN4core3ops6FnOnce9call_once", - "core::ops::FnOnce::call_once", - // tests - "_ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce\ - $LT$$LP$$RP$$GT$$GT$9call_once", + // test::run_test + "ZN4test8run_test", + // as core::ops::FnOnce<()>>::call_once "ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce\ $LT$$LP$$RP$$GT$$GT$9call_once", - " as core::ops::FnOnce<()>>::call_once", - - "_ZN4test8run_test", - "ZN4test8run_test", - "test::run_test", - - "_ZN42_$LT$F$u20$as$u20$test..FnBox$LT$T$GT$$GT$8call_box", + // >::call_box "ZN42_$LT$F$u20$as$u20$test..FnBox$LT$T$GT$$GT$8call_box", - ">::call_box", - ]; let is_good_frame = |frame: Frame, bad_prefixes: &[&str]| { resolve_symname(frame, |symname| { if let Some(mangled_symbol_name) = symname { - if !bad_prefixes.iter().any(|s| mangled_symbol_name.starts_with(s)) { + if !bad_prefixes.iter().any(|s| mangled_symbol_name.contains(s)) { return Ok(()) } } From 7d667e453139d8d5b9232154f10a1ee78d397a86 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Tue, 21 Mar 2017 17:19:59 -0400 Subject: [PATCH 09/17] [backtrace] use inline(never) functions instead of blacklist --- src/libstd/rt.rs | 14 ++++++++--- src/libstd/sys_common/backtrace.rs | 40 +++++------------------------- src/libtest/lib.rs | 23 ++++++++++++++--- 3 files changed, 37 insertions(+), 40 deletions(-) diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 78d5aa597ba0d..3721157e912d1 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -29,8 +29,7 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; #[cfg(not(test))] #[lang = "start"] -fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { - use mem; +fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { use panic; use sys; use sys_common; @@ -54,7 +53,9 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { sys::args::init(argc, argv); // Let's run some code! - let res = panic::catch_unwind(mem::transmute::<_, fn()>(main)); + let res = panic::catch_unwind(|| { + __rust_begin_backtrace_binary(main) + }); sys_common::cleanup(); res.is_err() }; @@ -65,3 +66,10 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { 0 } } + +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[no_mangle] +#[inline(never)] +pub fn __rust_begin_backtrace_binary(f: fn()) { + f() +} diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index f70bf60aa8e47..04986e6dca270 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -120,30 +120,8 @@ fn filter_frames(frames: &[Frame], "mingw_set_invalid_parameter_handler", ]; static BAD_PREFIXES_BOTTOM: &'static [&'static str] = &[ - // core::panicking - "ZN4core9panicking", - // std::panicking - "ZN3std9panicking", - // std::panic - "ZN3std5panic", - // core::ops::FnOnce::call_once - "ZN4core3ops6FnOnce9call_once", - - "__rust_try", - "BaseThreadInitThunk", - "RtlInitializeExceptionChain", - "__scrt_common_main_seh", - "_ZN4drop", - "mingw_set_invalid_parameter_handler", - - // tests - // test::run_test - "ZN4test8run_test", - // as core::ops::FnOnce<()>>::call_once - "ZN91_$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..FnOnce\ - $LT$$LP$$RP$$GT$$GT$9call_once", - // >::call_box - "ZN42_$LT$F$u20$as$u20$test..FnBox$LT$T$GT$$GT$8call_box", + "__rust_begin_backtrace_binary", + "__rust_begin_backtrace_test", ]; let is_good_frame = |frame: Frame, bad_prefixes: &[&str]| { @@ -160,25 +138,19 @@ fn filter_frames(frames: &[Frame], let skipped_before = frames.iter().position(|frame| { is_good_frame(*frame, BAD_PREFIXES_TOP) }).unwrap_or(frames.len()); - let idx_catch_panic = frames.iter().rposition(|frame| { + + let skipped_after = frames.iter().rev().position(|frame| { let mut is_rmcp = false; let _ = resolve_symname(*frame, |symname| { if let Some(mangled_symbol_name) = symname { - if mangled_symbol_name.contains("rust_maybe_catch_panic") { + if BAD_PREFIXES_BOTTOM.iter().any(|s| mangled_symbol_name.contains(s)) { is_rmcp = true; } } Ok(()) }, context); is_rmcp - }).unwrap_or(frames.len()); - let skipped_after = - frames.len() - idx_catch_panic - + frames[skipped_before..idx_catch_panic].iter() - .rev() - .position(|frame| { - is_good_frame(*frame, BAD_PREFIXES_BOTTOM) - }).unwrap_or(0); + }).map(|x| x + 1 /* also ignore the marker frame */).unwrap_or(0); if skipped_before + skipped_after >= frames.len() { // Avoid showing completely empty backtraces diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 5fdb0aa0641a0..a9c1404af9424 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1363,12 +1363,29 @@ pub fn run_test(opts: &TestOpts, monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap(); return; } - DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f), - StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, - Box::new(move |()| f())), + DynTestFn(f) => + run_test_inner(desc, monitor_ch, opts.nocapture, + Box::new(move |()| __rust_begin_backtrace_test_boxfn(f))), + StaticTestFn(f) => + run_test_inner(desc, monitor_ch, opts.nocapture, + Box::new(move |()| __rust_begin_backtrace_test(f))), } } +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[no_mangle] +#[inline(never)] +pub fn __rust_begin_backtrace_test_boxfn(f: Box>) { + f.call_box(()) +} + +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[no_mangle] +#[inline(never)] +pub fn __rust_begin_backtrace_test(f: fn()) { + f() +} + fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> TestResult { match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | From 00b991e8ec4be2643f16d81cc6afc81f0e09ff54 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Tue, 21 Mar 2017 18:37:24 -0400 Subject: [PATCH 10/17] [backtrace] improve doc --- src/libstd/sys_common/backtrace.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 04986e6dca270..965fc46872eb3 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -93,6 +93,8 @@ fn _print(w: &mut Write, format: PrintFormat) -> io::Result<()> { Ok(()) } +/// Returns a number of frames to remove at the beginning and at the end of the +/// backtrace, according to the backtrace format. fn filter_frames(frames: &[Frame], format: PrintFormat, context: &BacktraceContext) -> (usize, usize) @@ -101,8 +103,10 @@ fn filter_frames(frames: &[Frame], return (0, 0); } - // We want to filter out frames with some prefixes - // from both top and bottom of the call stack. + // Frames to remove from the top of the backtrace. + // + // The raw form is used so that we don't have to demangle the symbol names. + // The `a::b::c` form can show up on Windows/MSVC. static BAD_PREFIXES_TOP: &'static [&'static str] = &[ // std::sys::imp::backtrace "ZN3std3sys3imp9backtrace", @@ -119,6 +123,9 @@ fn filter_frames(frames: &[Frame], "_ZN4drop", "mingw_set_invalid_parameter_handler", ]; + + // All the frames after these symbols will be removed. + // See `rt.rs` and `libtest` for their generation. static BAD_PREFIXES_BOTTOM: &'static [&'static str] = &[ "__rust_begin_backtrace_binary", "__rust_begin_backtrace_test", @@ -140,16 +147,16 @@ fn filter_frames(frames: &[Frame], }).unwrap_or(frames.len()); let skipped_after = frames.iter().rev().position(|frame| { - let mut is_rmcp = false; + let mut is_marker = false; let _ = resolve_symname(*frame, |symname| { if let Some(mangled_symbol_name) = symname { if BAD_PREFIXES_BOTTOM.iter().any(|s| mangled_symbol_name.contains(s)) { - is_rmcp = true; + is_marker = true; } } Ok(()) }, context); - is_rmcp + is_marker }).map(|x| x + 1 /* also ignore the marker frame */).unwrap_or(0); if skipped_before + skipped_after >= frames.len() { From 5205b8d6f5efdf3884f0f642516a506195f8e384 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Tue, 21 Mar 2017 18:37:46 -0400 Subject: [PATCH 11/17] [backtrace] Re-add MSVC handling See https://github.com/rust-lang/rust/pull/40264/files#r106747897 --- src/libstd/sys_common/backtrace.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 965fc46872eb3..3e49e5e322469 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -108,15 +108,19 @@ fn filter_frames(frames: &[Frame], // The raw form is used so that we don't have to demangle the symbol names. // The `a::b::c` form can show up on Windows/MSVC. static BAD_PREFIXES_TOP: &'static [&'static str] = &[ - // std::sys::imp::backtrace + "std::sys::imp::backtrace", "ZN3std3sys3imp9backtrace", - // std::sys_common::backtrace + + "std::sys_common::backtrace", "ZN3std10sys_common9backtrace", - // std::panicking + + "std::panicking", "ZN3std9panicking", - // core::panicking + + "core::panicking", "ZN4core9panicking", - // core::result::unwrap_failed + + "core::result::unwrap_failed", "ZN4core6result13unwrap_failed", "rust_begin_unwind", From 8a75b2056f61287e50280edfaf29f769ab343b67 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Thu, 23 Mar 2017 11:22:29 -0400 Subject: [PATCH 12/17] Use private mangled __rust_begin_short_backtrace_* --- src/libstd/rt.rs | 5 ++--- src/libstd/sys_common/backtrace.rs | 10 ++-------- src/libtest/lib.rs | 10 ++++------ 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 3721157e912d1..f4a16ad0939a5 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -54,7 +54,7 @@ fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { // Let's run some code! let res = panic::catch_unwind(|| { - __rust_begin_backtrace_binary(main) + __rust_begin_short_backtrace_binary(main) }); sys_common::cleanup(); res.is_err() @@ -68,8 +68,7 @@ fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { } /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. -#[no_mangle] #[inline(never)] -pub fn __rust_begin_backtrace_binary(f: fn()) { +fn __rust_begin_short_backtrace_binary(f: fn()) { f() } diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 3e49e5e322469..b5684818724ab 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -128,13 +128,6 @@ fn filter_frames(frames: &[Frame], "mingw_set_invalid_parameter_handler", ]; - // All the frames after these symbols will be removed. - // See `rt.rs` and `libtest` for their generation. - static BAD_PREFIXES_BOTTOM: &'static [&'static str] = &[ - "__rust_begin_backtrace_binary", - "__rust_begin_backtrace_test", - ]; - let is_good_frame = |frame: Frame, bad_prefixes: &[&str]| { resolve_symname(frame, |symname| { if let Some(mangled_symbol_name) = symname { @@ -154,7 +147,8 @@ fn filter_frames(frames: &[Frame], let mut is_marker = false; let _ = resolve_symname(*frame, |symname| { if let Some(mangled_symbol_name) = symname { - if BAD_PREFIXES_BOTTOM.iter().any(|s| mangled_symbol_name.contains(s)) { + // Use grep to find the concerned functions + if mangled_symbol_name.contains("__rust_begin_short_backtrace_") { is_marker = true; } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index a9c1404af9424..f23f7446a2154 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1365,24 +1365,22 @@ pub fn run_test(opts: &TestOpts, } DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, - Box::new(move |()| __rust_begin_backtrace_test_boxfn(f))), + Box::new(move |()| __rust_begin_short_backtrace_test_boxfn(f))), StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, - Box::new(move |()| __rust_begin_backtrace_test(f))), + Box::new(move |()| __rust_begin_short_backtrace_test(f))), } } /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. -#[no_mangle] #[inline(never)] -pub fn __rust_begin_backtrace_test_boxfn(f: Box>) { +fn __rust_begin_short_backtrace_test_boxfn(f: Box>) { f.call_box(()) } /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. -#[no_mangle] #[inline(never)] -pub fn __rust_begin_backtrace_test(f: fn()) { +fn __rust_begin_short_backtrace_test(f: fn()) { f() } From 03f9940f3a952b15e0bed863da3883e10f2b2a5c Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Thu, 23 Mar 2017 11:22:41 -0400 Subject: [PATCH 13/17] Handle threads --- src/libstd/thread/mod.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 2bc066d3fea55..7d3491a4afbf3 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -357,7 +357,9 @@ impl Builder { } unsafe { thread_info::set(imp::guard::current(), their_thread); - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f)); + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + __rust_begin_short_backtrace_thread(f) + })); *their_packet.get() = Some(try_result); } }; @@ -372,6 +374,14 @@ impl Builder { } } +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[inline(never)] +fn __rust_begin_short_backtrace_thread(f: F) -> T + where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static +{ + f() +} + //////////////////////////////////////////////////////////////////////////////// // Free functions //////////////////////////////////////////////////////////////////////////////// From b36446a327421e2e2ba4d8fa13407cb2b43c4eb9 Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Thu, 23 Mar 2017 12:21:26 -0400 Subject: [PATCH 14/17] Use first found frame instead of last Tests use a thread, so the backtrace would not be cleaned enough --- src/libstd/sys_common/backtrace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index b5684818724ab..ad642c725bb50 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -143,7 +143,7 @@ fn filter_frames(frames: &[Frame], is_good_frame(*frame, BAD_PREFIXES_TOP) }).unwrap_or(frames.len()); - let skipped_after = frames.iter().rev().position(|frame| { + let skipped_after = frames.len() - frames.iter().position(|frame| { let mut is_marker = false; let _ = resolve_symname(*frame, |symname| { if let Some(mangled_symbol_name) = symname { @@ -155,7 +155,7 @@ fn filter_frames(frames: &[Frame], Ok(()) }, context); is_marker - }).map(|x| x + 1 /* also ignore the marker frame */).unwrap_or(0); + }).unwrap_or(frames.len()); if skipped_before + skipped_after >= frames.len() { // Avoid showing completely empty backtraces From 0e16333496a5850c91720876bdf4cc685dabc5fd Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Thu, 23 Mar 2017 12:34:17 -0400 Subject: [PATCH 15/17] Better cleaning of benchmarks --- src/libtest/lib.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f23f7446a2154..54166325422f3 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1252,12 +1252,16 @@ pub fn convert_benchmarks_to_tests(tests: Vec) -> Vec { DynTestFn(Box::new(move |()| { - bench::run_once(|b| bench.run(b)) + bench::run_once(|b| { + __rust_begin_short_backtrace_bench_dyn(&bench, b) + }) })) } StaticBenchFn(benchfn) => { DynTestFn(Box::new(move |()| { - bench::run_once(|b| benchfn(b)) + bench::run_once(|b| { + __rust_begin_short_backtrace_bench_static(benchfn, b) + }) })) } f => f, @@ -1384,6 +1388,18 @@ fn __rust_begin_short_backtrace_test(f: fn()) { f() } +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[inline(never)] +fn __rust_begin_short_backtrace_bench_static(f: fn(&mut Bencher), b: &mut Bencher) { + f(b) +} + +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[inline(never)] +fn __rust_begin_short_backtrace_bench_dyn(bench: &Box, b: &mut Bencher) { + bench.run(b) +} + fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> TestResult { match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | From e1ca6266e6d7d249ceeabecf3af9e04d6926d27a Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Mon, 27 Mar 2017 17:56:34 -0400 Subject: [PATCH 16/17] Use unique backtrace start frame for all std --- src/libstd/rt.rs | 8 +------- src/libstd/sys_common/backtrace.rs | 11 ++++++++++- src/libstd/thread/mod.rs | 10 +--------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index f4a16ad0939a5..792bdd31e93be 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -54,7 +54,7 @@ fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { // Let's run some code! let res = panic::catch_unwind(|| { - __rust_begin_short_backtrace_binary(main) + ::sys_common::backtrace::__rust_begin_short_backtrace(main) }); sys_common::cleanup(); res.is_err() @@ -66,9 +66,3 @@ fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { 0 } } - -/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. -#[inline(never)] -fn __rust_begin_short_backtrace_binary(f: fn()) { - f() -} diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index ad642c725bb50..1423c948dd628 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -148,7 +148,7 @@ fn filter_frames(frames: &[Frame], let _ = resolve_symname(*frame, |symname| { if let Some(mangled_symbol_name) = symname { // Use grep to find the concerned functions - if mangled_symbol_name.contains("__rust_begin_short_backtrace_") { + if mangled_symbol_name.contains("__rust_begin_short_backtrace") { is_marker = true; } } @@ -165,6 +165,15 @@ fn filter_frames(frames: &[Frame], (skipped_before, skipped_after) } + +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[inline(never)] +pub fn __rust_begin_short_backtrace(f: F) -> T + where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static +{ + f() +} + /// Controls how the backtrace should be formated. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum PrintFormat { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 7d3491a4afbf3..5d4f1e5b0c90d 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -358,7 +358,7 @@ impl Builder { unsafe { thread_info::set(imp::guard::current(), their_thread); let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - __rust_begin_short_backtrace_thread(f) + ::sys_common::backtrace::__rust_begin_short_backtrace(f) })); *their_packet.get() = Some(try_result); } @@ -374,14 +374,6 @@ impl Builder { } } -/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. -#[inline(never)] -fn __rust_begin_short_backtrace_thread(f: F) -> T - where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static -{ - f() -} - //////////////////////////////////////////////////////////////////////////////// // Free functions //////////////////////////////////////////////////////////////////////////////// From d72937df1ed84b3c5405f6316ace0119aa57d80e Mon Sep 17 00:00:00 2001 From: Yamakaky Date: Mon, 27 Mar 2017 18:04:20 -0400 Subject: [PATCH 17/17] Unused frames --- src/libstd/sys_common/backtrace.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 1423c948dd628..1c9c94becf921 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -124,8 +124,6 @@ fn filter_frames(frames: &[Frame], "ZN4core6result13unwrap_failed", "rust_begin_unwind", - "_ZN4drop", - "mingw_set_invalid_parameter_handler", ]; let is_good_frame = |frame: Frame, bad_prefixes: &[&str]| {