Skip to content

Commit

Permalink
Explicitly count the number of panics
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ranma42 committed Sep 24, 2015
1 parent 44d1b14 commit c7b8490
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 20 deletions.
24 changes: 22 additions & 2 deletions src/libstd/panicking.rs
Expand Up @@ -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<usize> = Cell::new(0) }

thread_local! {
pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
Expand Down Expand Up @@ -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() }
}
}
22 changes: 4 additions & 18 deletions src/libstd/sys/common/unwind/mod.rs
Expand Up @@ -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;
Expand All @@ -92,8 +91,6 @@ pub mod imp;
#[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
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -161,7 +158,7 @@ pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {

/// 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
Expand Down Expand Up @@ -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);
}

0 comments on commit c7b8490

Please sign in to comment.