diff options
| author | Steven Fackler <sfackler@gmail.com> | 2015-12-25 12:00:40 -0700 |
|---|---|---|
| committer | Steven Fackler <sfackler@gmail.com> | 2016-01-06 16:06:11 -0800 |
| commit | 022c9c70c48581b8caa17895b447a941a9750076 (patch) | |
| tree | 37b70c488759bebaff9b5312d2829f3af5f3c804 | |
| parent | 5b838c586c4da31395d614d9f076430314fa05ff (diff) | |
| download | rust-022c9c70c48581b8caa17895b447a941a9750076.tar.gz rust-022c9c70c48581b8caa17895b447a941a9750076.zip | |
Add std::panic::propagate
| -rw-r--r-- | src/libstd/panic.rs | 27 | ||||
| -rw-r--r-- | src/libstd/sys/common/unwind/mod.rs | 2 | ||||
| -rw-r--r-- | src/test/run-pass/panic-recover-propagate.rs | 35 |
3 files changed, 63 insertions, 1 deletions
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index b42d1d1b8d4..f6931f21eb9 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -13,6 +13,8 @@ #![unstable(feature = "std_panic", reason = "awaiting feedback", issue = "27719")] +use any::Any; +use boxed::Box; use cell::UnsafeCell; use ops::{Deref, DerefMut}; use ptr::{Unique, Shared}; @@ -259,3 +261,28 @@ pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> { } Ok(result.unwrap()) } + +/// Triggers a panic without invoking the panic handler. +/// +/// This is designed to be used in conjunction with `recover` to, for example, +/// carry a panic across a layer of C code. +/// +/// # Examples +/// +/// ```should_panic +/// #![feature(std_panic, recover, panic_propagate)] +/// +/// use std::panic; +/// +/// let result = panic::recover(|| { +/// panic!("oh no!"); +/// }); +/// +/// if let Err(err) = result { +/// panic::propagate(err); +/// } +/// ``` +#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")] +pub fn propagate(payload: Box<Any + Send>) -> ! { + unwind::rust_panic(payload) +} diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs index 0f10e727461..666b2ed72ad 100644 --- a/src/libstd/sys/common/unwind/mod.rs +++ b/src/libstd/sys/common/unwind/mod.rs @@ -172,7 +172,7 @@ pub fn panicking() -> bool { #[inline(never)] #[no_mangle] #[allow(private_no_mangle_fns)] -fn rust_panic(cause: Box<Any + Send + 'static>) -> ! { +pub fn rust_panic(cause: Box<Any + Send + 'static>) -> ! { unsafe { imp::panic(cause) } diff --git a/src/test/run-pass/panic-recover-propagate.rs b/src/test/run-pass/panic-recover-propagate.rs new file mode 100644 index 00000000000..c0b2f25d99c --- /dev/null +++ b/src/test/run-pass/panic-recover-propagate.rs @@ -0,0 +1,35 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(std_panic, recover, panic_propagate, panic_handler, const_fn)] + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::panic; +use std::thread; + +static A: AtomicUsize = AtomicUsize::new(0); + +fn main() { + panic::set_handler(|_| { + A.fetch_add(1, Ordering::SeqCst); + }); + + let result = thread::spawn(|| { + let result = panic::recover(|| { + panic!("hi there"); + }); + + panic::propagate(result.err().unwrap()); + }).join(); + + let msg = *result.err().unwrap().downcast::<&'static str>().unwrap(); + assert_eq!("hi there", msg); + assert_eq!(1, A.load(Ordering::SeqCst)); +} |
