@@ -76,6 +76,12 @@ enum Hook {
7676 Custom ( * mut ( dyn Fn ( & PanicInfo < ' _ > ) + ' static + Sync + Send ) ) ,
7777}
7878
79+ impl Hook {
80+ fn custom ( f : impl Fn ( & PanicInfo < ' _ > ) + ' static + Sync + Send ) -> Self {
81+ Self :: Custom ( Box :: into_raw ( Box :: new ( f) ) )
82+ }
83+ }
84+
7985static HOOK_LOCK : StaticRWLock = StaticRWLock :: new ( ) ;
8086static mut HOOK : Hook = Hook :: Default ;
8187
@@ -180,7 +186,8 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
180186 }
181187}
182188
183- /// Atomic combination of [`take_hook`] + [`set_hook`].
189+ /// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with
190+ /// a new panic handler that does something and then executes the old handler.
184191///
185192/// [`take_hook`]: ./fn.take_hook.html
186193/// [`set_hook`]: ./fn.set_hook.html
@@ -189,16 +196,6 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
189196///
190197/// Panics if called from a panicking thread.
191198///
192- /// Panics if the provided closure calls any of the functions [`panic::take_hook`],
193- /// [`panic::set_hook`], or [`panic::update_hook`].
194- ///
195- /// Note: if the provided closure panics, the panic will not be able to be handled, resulting in a
196- /// double panic that aborts the process with a generic error message.
197- ///
198- /// [`panic::take_hook`]: ./fn.take_hook.html
199- /// [`panic::set_hook`]: ./fn.set_hook.html
200- /// [`panic::update_hook`]: ./fn.update_hook.html
201- ///
202199/// # Examples
203200///
204201/// The following will print the custom message, and then the normal output of panic.
@@ -207,21 +204,26 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
207204/// #![feature(panic_update_hook)]
208205/// use std::panic;
209206///
210- /// panic::update_hook(|prev| {
211- /// Box::new(move |panic_info| {
212- /// println!("Print custom message and execute panic handler as usual");
213- /// prev(panic_info);
214- /// })
207+ /// // Equivalent to
208+ /// // let prev = panic::take_hook();
209+ /// // panic::set_hook(move |info| {
210+ /// // println!("...");
211+ /// // prev(info);
212+ /// // );
213+ /// panic::update_hook(move |prev, info| {
214+ /// println!("Print custom message and execute panic handler as usual");
215+ /// prev(info);
215216/// });
216217///
217218/// panic!("Custom and then normal");
218219/// ```
219220#[ unstable( feature = "panic_update_hook" , issue = "92649" ) ]
220221pub fn update_hook < F > ( hook_fn : F )
221222where
222- F : FnOnce (
223- Box < dyn Fn ( & PanicInfo < ' _ > ) + ' static + Sync + Send > ,
224- ) -> Box < dyn Fn ( & PanicInfo < ' _ > ) + ' static + Sync + Send > ,
223+ F : Fn ( & ( dyn Fn ( & PanicInfo < ' _ > ) + Send + Sync + ' static ) , & PanicInfo < ' _ > )
224+ + Sync
225+ + Send
226+ + ' static ,
225227{
226228 if thread:: panicking ( ) {
227229 panic ! ( "cannot modify the panic hook from a panicking thread" ) ;
@@ -232,13 +234,12 @@ where
232234 let old_hook = HOOK ;
233235 HOOK = Hook :: Default ;
234236
235- let hook_for_fn = match old_hook {
237+ let prev = match old_hook {
236238 Hook :: Default => Box :: new ( default_hook) ,
237239 Hook :: Custom ( ptr) => Box :: from_raw ( ptr) ,
238240 } ;
239241
240- let hook = hook_fn ( hook_for_fn) ;
241- HOOK = Hook :: Custom ( Box :: into_raw ( hook) ) ;
242+ HOOK = Hook :: custom ( move |info| hook_fn ( & prev, info) ) ;
242243 drop ( guard) ;
243244 }
244245}
0 commit comments