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.
This commit is contained in:
Andrea Canciani 2015-09-24 23:49:38 +02:00
parent 44d1b149d2
commit c7b84909b0
2 changed files with 26 additions and 20 deletions

View File

@ -12,11 +12,15 @@
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<usize> = Cell::new(0) }
thread_local! {
pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
@ -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() }
}
}

View File

@ -64,9 +64,8 @@
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 @@
#[path = "gcc.rs"] #[doc(hidden)]
pub mod imp;
thread_local! { static PANICKING: Cell<bool> = 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: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
// care of exposing correctly.
unsafe fn inner_try(f: fn(*mut u8), data: *mut u8)
-> Result<(), Box<Any + Send>> {
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 @@ fn rust_try(f: extern fn(*mut u8),
/// 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<Any + Send>,
// 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);
}