about summary refs log tree commit diff
path: root/library/std/src/panicking.rs
diff options
context:
space:
mode:
authorBadel2 <2badel2@gmail.com>2022-01-07 17:04:33 +0100
committerBadel2 <2badel2@gmail.com>2022-01-08 00:57:59 +0100
commit8ef3ce866e2f20bdcc567e2f7012f81ce2e60298 (patch)
tree1764db087c7b3bb38aa060ba67b985d4ec63f975 /library/std/src/panicking.rs
parent8bdf5c3de6c6e4e01f7f6241cd0f2a606c7486df (diff)
downloadrust-8ef3ce866e2f20bdcc567e2f7012f81ce2e60298.tar.gz
rust-8ef3ce866e2f20bdcc567e2f7012f81ce2e60298.zip
Change panic::update_hook to simplify usage
And to remove possibility of panics while changing the panic handler,
because that resulted in a double panic.
Diffstat (limited to 'library/std/src/panicking.rs')
-rw-r--r--library/std/src/panicking.rs45
1 files changed, 23 insertions, 22 deletions
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index cf970dccfc9..19040cb12e0 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -76,6 +76,12 @@ enum Hook {
     Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)),
 }
 
+impl Hook {
+    fn custom(f: impl Fn(&PanicInfo<'_>) + 'static + Sync + Send) -> Self {
+        Self::Custom(Box::into_raw(Box::new(f)))
+    }
+}
+
 static HOOK_LOCK: StaticRWLock = StaticRWLock::new();
 static mut HOOK: Hook = Hook::Default;
 
@@ -180,7 +186,8 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
     }
 }
 
-/// Atomic combination of [`take_hook`] + [`set_hook`].
+/// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with
+/// a new panic handler that does something and then executes the old handler.
 ///
 /// [`take_hook`]: ./fn.take_hook.html
 /// [`set_hook`]: ./fn.set_hook.html
@@ -189,16 +196,6 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
 ///
 /// Panics if called from a panicking thread.
 ///
-/// Panics if the provided closure calls any of the functions [`panic::take_hook`],
-/// [`panic::set_hook`], or [`panic::update_hook`].
-///
-/// Note: if the provided closure panics, the panic will not be able to be handled, resulting in a
-/// double panic that aborts the process with a generic error message.
-///
-/// [`panic::take_hook`]: ./fn.take_hook.html
-/// [`panic::set_hook`]: ./fn.set_hook.html
-/// [`panic::update_hook`]: ./fn.update_hook.html
-///
 /// # Examples
 ///
 /// The following will print the custom message, and then the normal output of panic.
@@ -207,11 +204,15 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
 /// #![feature(panic_update_hook)]
 /// use std::panic;
 ///
-/// panic::update_hook(|prev| {
-///     Box::new(move |panic_info| {
-///         println!("Print custom message and execute panic handler as usual");
-///         prev(panic_info);
-///     })
+/// // Equivalent to
+/// // let prev = panic::take_hook();
+/// // panic::set_hook(move |info| {
+/// //     println!("...");
+/// //     prev(info);
+/// // );
+/// panic::update_hook(move |prev, info| {
+///     println!("Print custom message and execute panic handler as usual");
+///     prev(info);
 /// });
 ///
 /// panic!("Custom and then normal");
@@ -219,9 +220,10 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
 #[unstable(feature = "panic_update_hook", issue = "92649")]
 pub fn update_hook<F>(hook_fn: F)
 where
-    F: FnOnce(
-        Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>,
-    ) -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>,
+    F: Fn(&(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static), &PanicInfo<'_>)
+        + Sync
+        + Send
+        + 'static,
 {
     if thread::panicking() {
         panic!("cannot modify the panic hook from a panicking thread");
@@ -232,13 +234,12 @@ where
         let old_hook = HOOK;
         HOOK = Hook::Default;
 
-        let hook_for_fn = match old_hook {
+        let prev = match old_hook {
             Hook::Default => Box::new(default_hook),
             Hook::Custom(ptr) => Box::from_raw(ptr),
         };
 
-        let hook = hook_fn(hook_for_fn);
-        HOOK = Hook::Custom(Box::into_raw(hook));
+        HOOK = Hook::custom(move |info| hook_fn(&prev, info));
         drop(guard);
     }
 }