From ca99468f386fdfe082589d437f12d0b9b558f980 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Tue, 12 Jun 2018 08:16:03 +0100 Subject: [PATCH] Helpful stack overflow messages. This is using libunwind, though the library is called this, it does't actually unwind the stack in our case (which is good as this preserves panic safety). --- src/libstd/sys_common/util.rs | 20 ++++++++++++++++++++ src/test/run-pass/stack-probes.rs | 1 + 2 files changed, 21 insertions(+) diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs index a373e980b970d..c70d8ac15d31a 100644 --- a/src/libstd/sys_common/util.rs +++ b/src/libstd/sys_common/util.rs @@ -13,6 +13,9 @@ use io::prelude::*; use sys::stdio::{Stderr, stderr_prints_nothing}; use thread; +#[cfg(feature = "backtrace")] +use sys_common::backtrace; + pub fn dumb_print(args: fmt::Arguments) { if stderr_prints_nothing() { return @@ -34,4 +37,21 @@ pub fn abort(args: fmt::Arguments) -> ! { pub unsafe fn report_overflow() { dumb_print(format_args!("\nthread '{}' has overflowed its stack\n", thread::current().name().unwrap_or(""))); + + #[cfg(feature = "backtrace")] + { + let log_backtrace = backtrace::log_enabled(); + + use sync::atomic::{AtomicBool, Ordering}; + + static FIRST_OVERFLOW: AtomicBool = AtomicBool::new(true); + + if let Some(format) = log_backtrace { + if let Ok(mut stderr) = Stderr::new() { + let _ = backtrace::print(&mut stderr, format); + } + } else if FIRST_OVERFLOW.compare_and_swap(true, false, Ordering::SeqCst) { + dumb_print(format_args!("note: Run with `RUST_BACKTRACE=1` for a backtrace.")); + } + } } diff --git a/src/test/run-pass/stack-probes.rs b/src/test/run-pass/stack-probes.rs index c93dcf019397b..6ca51620adcfc 100644 --- a/src/test/run-pass/stack-probes.rs +++ b/src/test/run-pass/stack-probes.rs @@ -73,4 +73,5 @@ fn assert_overflow(cmd: &mut Command) { println!("stderr: {}", stderr); assert!(stdout.is_empty()); assert!(stderr.contains("has overflowed its stack\n")); + assert!(stderr.contains("::")); }