From c7b84909b00dcf5f762778b4aa9783770c69416d Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Thu, 24 Sep 2015 23:49:38 +0200 Subject: [PATCH] Explicitly count the number of panics Move the panic handling logic from the `unwind` module to `panicking` and use a panic counter to distinguish between normal state, panics and double panics. --- src/libstd/panicking.rs | 24 ++++++++++++++++++++++-- src/libstd/sys/common/unwind/mod.rs | 22 ++++------------------ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 01a3900f24fc..fc242dee99fe 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -12,11 +12,15 @@ use prelude::v1::*; use io::prelude::*; use any::Any; +use cell::Cell; use cell::RefCell; +use intrinsics; use sys::stdio::Stderr; use sys_common::backtrace; use sys_common::thread_info; -use sys_common::unwind; +use sys_common::util; + +thread_local! { pub static PANIC_COUNT: Cell = Cell::new(0) } thread_local! { pub static LOCAL_STDERR: RefCell>> = { @@ -61,8 +65,24 @@ fn log_panic(obj: &(Any+Send), file: &'static str, line: u32, } pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) { + let panics = PANIC_COUNT.with(|s| { + let count = s.get() + 1; + s.set(count); + count + }); + // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. - let log_backtrace = unwind::panicking() || backtrace::log_enabled(); + let log_backtrace = panics >= 2 || backtrace::log_enabled(); log_panic(obj, file, line, log_backtrace); + + if panics >= 2 { + // If a thread panics while it's already unwinding then we + // have limited options. Currently our preference is to + // just abort. In the future we may consider resuming + // unwinding or otherwise exiting the thread cleanly. + util::dumb_print(format_args!("thread panicked while panicking. \ + aborting.")); + unsafe { intrinsics::abort() } + } } diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs index 8148bb6b7b82..c06d7886a757 100644 --- a/src/libstd/sys/common/unwind/mod.rs +++ b/src/libstd/sys/common/unwind/mod.rs @@ -64,9 +64,8 @@ use prelude::v1::*; use any::Any; use boxed; -use cell::Cell; use cmp; -use panicking; +use panicking::{self,PANIC_COUNT}; use fmt; use intrinsics; use mem; @@ -92,8 +91,6 @@ pub mod imp; #[path = "gcc.rs"] #[doc(hidden)] pub mod imp; -thread_local! { static PANICKING: Cell = Cell::new(false) } - /// Invoke a closure, capturing the cause of panic if one occurs. /// /// This function will return `Ok(())` if the closure did not panic, and will @@ -131,9 +128,9 @@ pub unsafe fn try(f: F) -> Result<(), Box> { // care of exposing correctly. unsafe fn inner_try(f: fn(*mut u8), data: *mut u8) -> Result<(), Box> { - PANICKING.with(|s| { + PANIC_COUNT.with(|s| { let prev = s.get(); - s.set(false); + s.set(0); let ep = intrinsics::try(f, data); s.set(prev); if ep.is_null() { @@ -161,7 +158,7 @@ pub unsafe fn try(f: F) -> Result<(), Box> { /// Determines whether the current thread is unwinding because of panic. pub fn panicking() -> bool { - PANICKING.with(|s| s.get()) + PANIC_COUNT.with(|s| s.get() != 0) } // An uninlined, unmangled function upon which to slap yer breakpoints @@ -234,17 +231,6 @@ fn begin_unwind_inner(msg: Box, // First, invoke the default panic handler. panicking::on_panic(&*msg, file, line); - if panicking() { - // If a thread panics while it's already unwinding then we - // have limited options. Currently our preference is to - // just abort. In the future we may consider resuming - // unwinding or otherwise exiting the thread cleanly. - super::util::dumb_print(format_args!("thread panicked while panicking. \ - aborting.")); - unsafe { intrinsics::abort() } - } - PANICKING.with(|s| s.set(true)); - // Finally, perform the unwinding. rust_panic(msg); }