mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-04 04:39:16 +00:00
std: Move the panic flag to its own thread local
This flag is somewhat tied to the `unwind` module rather than the `thread_info` module, so this commit moves it into that module as well as allowing the same OS thread to call `unwind::try` multiple times. Previously once a thread panicked its panic flag was never reset, even after exiting the panic handler.
This commit is contained in:
parent
5759cff48e
commit
d08600b189
@ -10,21 +10,15 @@
|
||||
|
||||
#![experimental]
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use prelude::*;
|
||||
|
||||
use any::{Any, AnyRefExt};
|
||||
use cell::RefCell;
|
||||
use fmt;
|
||||
use io::{Writer, IoResult};
|
||||
use kinds::Send;
|
||||
use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
use result::Result::Ok;
|
||||
use rt::backtrace;
|
||||
use io::IoResult;
|
||||
use rt::{backtrace, unwind};
|
||||
use rt::util::{Stderr, Stdio};
|
||||
use str::Str;
|
||||
use string::String;
|
||||
use thread::Thread;
|
||||
use sys_common::thread_info;
|
||||
|
||||
// Defined in this module instead of io::stdio so that the unwinding
|
||||
thread_local! {
|
||||
@ -80,7 +74,7 @@ pub fn on_fail(obj: &(Any+Send), file: &'static str, line: uint) {
|
||||
|
||||
// If this is a double panic, make sure that we printed a backtrace
|
||||
// for this panic.
|
||||
if thread_info::panicking() && !backtrace::log_enabled() {
|
||||
if unwind::panicking() && !backtrace::log_enabled() {
|
||||
let _ = backtrace::write(&mut err);
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,7 @@
|
||||
use prelude::*;
|
||||
|
||||
use any::Any;
|
||||
use cell::Cell;
|
||||
use cmp;
|
||||
use failure;
|
||||
use fmt;
|
||||
@ -69,7 +70,6 @@ use mem;
|
||||
use sync::atomic;
|
||||
use sync::{Once, ONCE_INIT};
|
||||
|
||||
use sys_common::thread_info;
|
||||
use rt::libunwind as uw;
|
||||
|
||||
struct Exception {
|
||||
@ -94,6 +94,8 @@ static CALLBACKS: [atomic::AtomicUint, ..MAX_CALLBACKS] =
|
||||
atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT];
|
||||
static CALLBACK_CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;
|
||||
|
||||
thread_local!(static PANICKING: Cell<bool> = Cell::new(false))
|
||||
|
||||
/// Invoke a closure, capturing the cause of panic if one occurs.
|
||||
///
|
||||
/// This function will return `None` if the closure did not panic, and will
|
||||
@ -116,7 +118,11 @@ static CALLBACK_CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;
|
||||
/// run.
|
||||
pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
|
||||
let mut f = Some(f);
|
||||
|
||||
let prev = PANICKING.with(|s| s.get());
|
||||
PANICKING.with(|s| s.set(false));
|
||||
let ep = rust_try(try_fn::<F>, &mut f as *mut _ as *mut c_void);
|
||||
PANICKING.with(|s| s.set(prev));
|
||||
return if ep.is_null() {
|
||||
Ok(())
|
||||
} else {
|
||||
@ -146,6 +152,11 @@ pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Test if the current thread is currently panicking.
|
||||
pub fn panicking() -> bool {
|
||||
PANICKING.with(|s| s.get())
|
||||
}
|
||||
|
||||
// An uninlined, unmangled function upon which to slap yer breakpoints
|
||||
#[inline(never)]
|
||||
#[no_mangle]
|
||||
@ -561,15 +572,15 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
|
||||
|
||||
// Now that we've run all the necessary unwind callbacks, we actually
|
||||
// perform the unwinding.
|
||||
if thread_info::panicking() {
|
||||
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 task cleanly.
|
||||
rterrln!("task failed during unwinding. aborting.");
|
||||
rterrln!("thread panicked while panicking. aborting.");
|
||||
unsafe { intrinsics::abort() }
|
||||
}
|
||||
thread_info::set_unwinding(true);
|
||||
PANICKING.with(|s| s.set(true));
|
||||
rust_panic(msg);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ struct ThreadInfo {
|
||||
// hence this is optional.
|
||||
stack_bounds: (uint, uint),
|
||||
stack_guard: uint,
|
||||
unwinding: bool,
|
||||
thread: Thread,
|
||||
}
|
||||
|
||||
@ -38,7 +37,6 @@ impl ThreadInfo {
|
||||
*c.borrow_mut() = Some(ThreadInfo {
|
||||
stack_bounds: (0, 0),
|
||||
stack_guard: 0,
|
||||
unwinding: false,
|
||||
thread: NewThread::new(None),
|
||||
})
|
||||
}
|
||||
@ -51,24 +49,15 @@ pub fn current_thread() -> Thread {
|
||||
ThreadInfo::with(|info| info.thread.clone())
|
||||
}
|
||||
|
||||
pub fn panicking() -> bool {
|
||||
ThreadInfo::with(|info| info.unwinding)
|
||||
}
|
||||
|
||||
pub fn stack_guard() -> uint {
|
||||
ThreadInfo::with(|info| info.stack_guard)
|
||||
}
|
||||
|
||||
pub fn set_unwinding(unwinding: bool) {
|
||||
ThreadInfo::with(|info| info.unwinding = unwinding)
|
||||
}
|
||||
|
||||
pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
|
||||
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
|
||||
THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
|
||||
stack_bounds: stack_bounds,
|
||||
stack_guard: stack_guard,
|
||||
unwinding: false,
|
||||
thread: thread,
|
||||
}));
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ impl Thread {
|
||||
|
||||
/// Determines whether the current thread is panicking.
|
||||
pub fn panicking() -> bool {
|
||||
thread_info::panicking()
|
||||
unwind::panicking()
|
||||
}
|
||||
|
||||
/// Block unless or until the current thread's token is made available (may wake spuriously).
|
||||
|
Loading…
Reference in New Issue
Block a user