diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-12-17 14:59:20 -0800 |
|---|---|---|
| committer | Aaron Turon <aturon@mozilla.com> | 2014-12-18 23:35:52 -0800 |
| commit | d08600b189eeb2e61879b44a07f9fdc33fa82689 (patch) | |
| tree | 274743c02df19bff0de04f5c9098f8c280d29c23 /src/libstd | |
| parent | 5759cff48e66bcf2bf2cf821211bdf683292d8f3 (diff) | |
| download | rust-d08600b189eeb2e61879b44a07f9fdc33fa82689.tar.gz rust-d08600b189eeb2e61879b44a07f9fdc33fa82689.zip | |
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.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/failure.rs | 16 | ||||
| -rw-r--r-- | src/libstd/rt/unwind.rs | 19 | ||||
| -rw-r--r-- | src/libstd/sys/common/thread_info.rs | 11 | ||||
| -rw-r--r-- | src/libstd/thread.rs | 2 |
4 files changed, 21 insertions, 27 deletions
diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs index 3934b0cf45f..8e1e3dc4af9 100644 --- a/src/libstd/failure.rs +++ b/src/libstd/failure.rs @@ -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); } } diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 8ef10cbbd77..9f34a72f807 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -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); } diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs index 92a896c7583..0519bc56f0a 100644 --- a/src/libstd/sys/common/thread_info.rs +++ b/src/libstd/sys/common/thread_info.rs @@ -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, })); } diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index 6c6c0ce85eb..8ef53a22aeb 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -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). |
