1
Fork 0

Auto merge of #32282 - sfackler:panic-hook, r=alexcrichton

Adjustments to the panic hook API

Rename `set_handler` and `take_handler` to `set_hook` and `take_hook` since we're not actually "handling" (i.e. fixing) anything.

Also alter `set_hook` to take a `Box<Fn(&PanicInfo) + 'static + Sync + Send>` rather than a parameterized closure since there's otherwise no easy way to re-register a hook that came from `take_hook`.

cc #30449

r? @aturon
This commit is contained in:
bors 2016-03-18 09:21:43 -07:00
commit 24bb607e7d
5 changed files with 67 additions and 55 deletions

View file

@ -23,7 +23,21 @@ use sync::{Arc, Mutex, RwLock};
use sys_common::unwind; use sys_common::unwind;
use thread::Result; use thread::Result;
pub use panicking::{take_handler, set_handler, PanicInfo, Location}; pub use panicking::{take_hook, set_hook, PanicInfo, Location};
///
#[rustc_deprecated(since = "1.9.0", reason = "renamed to set_hook")]
#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
pub fn set_handler<F>(handler: F) where F: Fn(&PanicInfo) + 'static + Sync + Send {
set_hook(Box::new(handler))
}
///
#[rustc_deprecated(since = "1.9.0", reason = "renamed to take_hook")]
#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
take_hook()
}
/// A marker trait which represents "panic safe" types in Rust. /// A marker trait which represents "panic safe" types in Rust.
/// ///

View file

@ -32,73 +32,71 @@ thread_local! {
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
enum Handler { enum Hook {
Default, Default,
Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)), Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)),
} }
static HANDLER_LOCK: StaticRwLock = StaticRwLock::new(); static HOOK_LOCK: StaticRwLock = StaticRwLock::new();
static mut HANDLER: Handler = Handler::Default; static mut HOOK: Hook = Hook::Default;
static FIRST_PANIC: AtomicBool = AtomicBool::new(true); static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
/// Registers a custom panic handler, replacing any that was previously /// Registers a custom panic hook, replacing any that was previously registered.
/// registered.
/// ///
/// The panic handler is invoked when a thread panics, but before it begins /// The panic hook is invoked when a thread panics, but before it begins
/// unwinding the stack. The default handler prints a message to standard error /// unwinding the stack. The default hook prints a message to standard error
/// and generates a backtrace if requested, but this behavior can be customized /// and generates a backtrace if requested, but this behavior can be customized
/// with the `set_handler` and `take_handler` functions. /// with the `set_hook` and `take_hook` functions.
/// ///
/// The handler is provided with a `PanicInfo` struct which contains information /// The hook is provided with a `PanicInfo` struct which contains information
/// about the origin of the panic, including the payload passed to `panic!` and /// about the origin of the panic, including the payload passed to `panic!` and
/// the source code location from which the panic originated. /// the source code location from which the panic originated.
/// ///
/// The panic handler is a global resource. /// The panic hook is a global resource.
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if called from a panicking thread. /// Panics if called from a panicking thread.
#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
pub fn set_handler<F>(handler: F) where F: Fn(&PanicInfo) + 'static + Sync + Send { pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
if thread::panicking() { if thread::panicking() {
panic!("cannot modify the panic handler from a panicking thread"); panic!("cannot modify the panic hook from a panicking thread");
} }
let handler = Box::new(handler);
unsafe { unsafe {
let lock = HANDLER_LOCK.write(); let lock = HOOK_LOCK.write();
let old_handler = HANDLER; let old_hook = HOOK;
HANDLER = Handler::Custom(Box::into_raw(handler)); HOOK = Hook::Custom(Box::into_raw(hook));
drop(lock); drop(lock);
if let Handler::Custom(ptr) = old_handler { if let Hook::Custom(ptr) = old_hook {
Box::from_raw(ptr); Box::from_raw(ptr);
} }
} }
} }
/// Unregisters the current panic handler, returning it. /// Unregisters the current panic hook, returning it.
/// ///
/// If no custom handler is registered, the default handler will be returned. /// If no custom hook is registered, the default hook will be returned.
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if called from a panicking thread. /// Panics if called from a panicking thread.
#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")] #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> { pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
if thread::panicking() { if thread::panicking() {
panic!("cannot modify the panic handler from a panicking thread"); panic!("cannot modify the panic hook from a panicking thread");
} }
unsafe { unsafe {
let lock = HANDLER_LOCK.write(); let lock = HOOK_LOCK.write();
let handler = HANDLER; let hook = HOOK;
HANDLER = Handler::Default; HOOK = Hook::Default;
drop(lock); drop(lock);
match handler { match hook {
Handler::Default => Box::new(default_handler), Hook::Default => Box::new(default_hook),
Handler::Custom(ptr) => {Box::from_raw(ptr)} // FIXME #30530 Hook::Custom(ptr) => {Box::from_raw(ptr)} // FIXME #30530
} }
} }
} }
@ -151,7 +149,7 @@ impl<'a> Location<'a> {
} }
} }
fn default_handler(info: &PanicInfo) { fn default_hook(info: &PanicInfo) {
let panics = PANIC_COUNT.with(|s| s.get()); let panics = PANIC_COUNT.with(|s| s.get());
// If this is a double panic, make sure that we print a backtrace // If this is a double panic, make sure that we print a backtrace
@ -224,10 +222,10 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
}; };
unsafe { unsafe {
let _lock = HANDLER_LOCK.read(); let _lock = HOOK_LOCK.read();
match HANDLER { match HOOK {
Handler::Default => default_handler(&info), Hook::Default => default_hook(&info),
Handler::Custom(ptr) => (*ptr)(&info), Hook::Custom(ptr) => (*ptr)(&info),
} }
} }

View file

@ -17,12 +17,12 @@ static A: AtomicUsize = AtomicUsize::new(0);
static B: AtomicUsize = AtomicUsize::new(0); static B: AtomicUsize = AtomicUsize::new(0);
fn main() { fn main() {
panic::set_handler(|_| { A.fetch_add(1, Ordering::SeqCst); }); panic::set_hook(Box::new(|_| { A.fetch_add(1, Ordering::SeqCst); }));
let handler = panic::take_handler(); let hook = panic::take_hook();
panic::set_handler(move |info| { panic::set_hook(Box::new(move |info| {
B.fetch_add(1, Ordering::SeqCst); B.fetch_add(1, Ordering::SeqCst);
handler(info); hook(info);
}); }));
let _ = thread::spawn(|| { let _ = thread::spawn(|| {
panic!(); panic!();

View file

@ -15,28 +15,28 @@ use std::panic;
use std::thread; use std::thread;
fn a() { fn a() {
panic::set_handler(|_| println!("hello yes this is a")); panic::set_hook(Box::new(|_| println!("hello yes this is a")));
panic::take_handler(); panic::take_hook();
panic::set_handler(|_| println!("hello yes this is a part 2")); panic::set_hook(Box::new(|_| println!("hello yes this is a part 2")));
panic::take_handler(); panic::take_hook();
} }
fn b() { fn b() {
panic::take_handler(); panic::take_hook();
panic::take_handler(); panic::take_hook();
panic::take_handler(); panic::take_hook();
panic::take_handler(); panic::take_hook();
panic::take_handler(); panic::take_hook();
panic!(); panic!();
} }
fn c() { fn c() {
panic::set_handler(|_| ()); panic::set_hook(Box::new(|_| ()));
panic::set_handler(|_| ()); panic::set_hook(Box::new(|_| ()));
panic::set_handler(|_| ()); panic::set_hook(Box::new(|_| ()));
panic::set_handler(|_| ()); panic::set_hook(Box::new(|_| ()));
panic::set_handler(|_| ()); panic::set_hook(Box::new(|_| ()));
panic::set_handler(|_| ()); panic::set_hook(Box::new(|_| ()));
panic!(); panic!();
} }

View file

@ -18,8 +18,8 @@ use std::thread;
static A: AtomicUsize = AtomicUsize::new(0); static A: AtomicUsize = AtomicUsize::new(0);
fn main() { fn main() {
panic::set_handler(|_| ()); panic::set_hook(Box::new(|_| ()));
panic::set_handler(|info| { A.fetch_add(1, Ordering::SeqCst); }); panic::set_hook(Box::new(|info| { A.fetch_add(1, Ordering::SeqCst); }));
let _ = thread::spawn(|| { let _ = thread::spawn(|| {
panic!(); panic!();