diff options
| author | bors <bors@rust-lang.org> | 2015-09-23 03:56:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-09-23 03:56:27 +0000 |
| commit | 07ca1ab1ec32ac99a61312ec07d66db5f3657040 (patch) | |
| tree | 2263ec09414f3b1c117a44df24cd00d84000f985 /src/libstd | |
| parent | cefe5f25b27b27c9d2f8685a7e16c852f9f77f60 (diff) | |
| parent | c6d277ade642a8cf166d6e4706add90fb9181ec2 (diff) | |
| download | rust-07ca1ab1ec32ac99a61312ec07d66db5f3657040.tar.gz rust-07ca1ab1ec32ac99a61312ec07d66db5f3657040.zip | |
Auto merge of #28585 - ranma42:simpler-panic, r=alexcrichton
This is part of some cleanup I did while investigating #28129. This also ensures that `on_panic` is run even if the user has registered too many callbacks.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/sys/common/unwind/mod.rs | 88 |
1 files changed, 5 insertions, 83 deletions
diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs index 8899d1b04d8..8148bb6b7b8 100644 --- a/src/libstd/sys/common/unwind/mod.rs +++ b/src/libstd/sys/common/unwind/mod.rs @@ -92,23 +92,6 @@ pub mod imp; #[path = "gcc.rs"] #[doc(hidden)] pub mod imp; -pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: u32); - -// Variables used for invoking callbacks when a thread starts to unwind. -// -// For more information, see below. -const MAX_CALLBACKS: usize = 16; -static CALLBACKS: [atomic::AtomicUsize; MAX_CALLBACKS] = - [atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0), - atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0), - atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0), - atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0), - atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0), - atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0), - atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0), - atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0)]; -static CALLBACK_CNT: atomic::AtomicUsize = atomic::AtomicUsize::new(0); - thread_local! { static PANICKING: Cell<bool> = Cell::new(false) } /// Invoke a closure, capturing the cause of panic if one occurs. @@ -246,45 +229,11 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, u32)) -> ! #[inline(never)] #[cold] // this is the slow path, please never inline this fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, u32)) -> ! { - // Make sure the default failure handler is registered before we look at the - // callbacks. We also use a raw sys-based mutex here instead of a - // `std::sync` one as accessing TLS can cause weird recursive problems (and - // we don't need poison checking). - unsafe { - static LOCK: Mutex = Mutex::new(); - static mut INIT: bool = false; - LOCK.lock(); - if !INIT { - register(panicking::on_panic); - INIT = true; - } - LOCK.unlock(); - } + let (file, line) = *file_line; - // First, invoke call the user-defined callbacks triggered on thread panic. - // - // By the time that we see a callback has been registered (by reading - // MAX_CALLBACKS), the actual callback itself may have not been stored yet, - // so we just chalk it up to a race condition and move on to the next - // callback. Additionally, CALLBACK_CNT may briefly be higher than - // MAX_CALLBACKS, so we're sure to clamp it as necessary. - let callbacks = { - let amt = CALLBACK_CNT.load(Ordering::SeqCst); - &CALLBACKS[..cmp::min(amt, MAX_CALLBACKS)] - }; - for cb in callbacks { - match cb.load(Ordering::SeqCst) { - 0 => {} - n => { - let f: Callback = unsafe { mem::transmute(n) }; - let (file, line) = *file_line; - f(&*msg, file, line); - } - } - }; + // First, invoke the default panic handler. + panicking::on_panic(&*msg, file, line); - // Now that we've run all the necessary unwind callbacks, we actually - // perform the unwinding. if panicking() { // If a thread panics while it's already unwinding then we // have limited options. Currently our preference is to @@ -295,34 +244,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, unsafe { intrinsics::abort() } } PANICKING.with(|s| s.set(true)); - rust_panic(msg); -} -/// Register a callback to be invoked when a thread unwinds. -/// -/// This is an unsafe and experimental API which allows for an arbitrary -/// callback to be invoked when a thread panics. This callback is invoked on both -/// the initial unwinding and a double unwinding if one occurs. Additionally, -/// the local `Thread` will be in place for the duration of the callback, and -/// the callback must ensure that it remains in place once the callback returns. -/// -/// Only a limited number of callbacks can be registered, and this function -/// returns whether the callback was successfully registered or not. It is not -/// currently possible to unregister a callback once it has been registered. -pub unsafe fn register(f: Callback) -> bool { - match CALLBACK_CNT.fetch_add(1, Ordering::SeqCst) { - // The invocation code has knowledge of this window where the count has - // been incremented, but the callback has not been stored. We're - // guaranteed that the slot we're storing into is 0. - n if n < MAX_CALLBACKS => { - let prev = CALLBACKS[n].swap(mem::transmute(f), Ordering::SeqCst); - rtassert!(prev == 0); - true - } - // If we accidentally bumped the count too high, pull it back. - _ => { - CALLBACK_CNT.store(MAX_CALLBACKS, Ordering::SeqCst); - false - } - } + // Finally, perform the unwinding. + rust_panic(msg); } |
