Skip to content

Commit 3ed6e9e

Browse files
committed
Auto merge of #30557 - sfackler:panic-propagate, r=aturon
See rust-lang/rfcs#1413. r? @alexcrichton
2 parents 43403b4 + 022c9c7 commit 3ed6e9e

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

src/libstd/panic.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#![unstable(feature = "std_panic", reason = "awaiting feedback",
1414
issue = "27719")]
1515

16+
use any::Any;
17+
use boxed::Box;
1618
use cell::UnsafeCell;
1719
use ops::{Deref, DerefMut};
1820
use ptr::{Unique, Shared};
@@ -259,3 +261,28 @@ pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> {
259261
}
260262
Ok(result.unwrap())
261263
}
264+
265+
/// Triggers a panic without invoking the panic handler.
266+
///
267+
/// This is designed to be used in conjunction with `recover` to, for example,
268+
/// carry a panic across a layer of C code.
269+
///
270+
/// # Examples
271+
///
272+
/// ```should_panic
273+
/// #![feature(std_panic, recover, panic_propagate)]
274+
///
275+
/// use std::panic;
276+
///
277+
/// let result = panic::recover(|| {
278+
/// panic!("oh no!");
279+
/// });
280+
///
281+
/// if let Err(err) = result {
282+
/// panic::propagate(err);
283+
/// }
284+
/// ```
285+
#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")]
286+
pub fn propagate(payload: Box<Any + Send>) -> ! {
287+
unwind::rust_panic(payload)
288+
}

src/libstd/sys/common/unwind/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ pub fn panicking() -> bool {
172172
#[inline(never)]
173173
#[no_mangle]
174174
#[allow(private_no_mangle_fns)]
175-
fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
175+
pub fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
176176
unsafe {
177177
imp::panic(cause)
178178
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(std_panic, recover, panic_propagate, panic_handler, const_fn)]
12+
13+
use std::sync::atomic::{AtomicUsize, Ordering};
14+
use std::panic;
15+
use std::thread;
16+
17+
static A: AtomicUsize = AtomicUsize::new(0);
18+
19+
fn main() {
20+
panic::set_handler(|_| {
21+
A.fetch_add(1, Ordering::SeqCst);
22+
});
23+
24+
let result = thread::spawn(|| {
25+
let result = panic::recover(|| {
26+
panic!("hi there");
27+
});
28+
29+
panic::propagate(result.err().unwrap());
30+
}).join();
31+
32+
let msg = *result.err().unwrap().downcast::<&'static str>().unwrap();
33+
assert_eq!("hi there", msg);
34+
assert_eq!(1, A.load(Ordering::SeqCst));
35+
}

0 commit comments

Comments
 (0)