@@ -76,6 +76,12 @@ enum Hook {
76
76
Custom ( * mut ( dyn Fn ( & PanicInfo < ' _ > ) + ' static + Sync + Send ) ) ,
77
77
}
78
78
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
+
79
85
static HOOK_LOCK : StaticRWLock = StaticRWLock :: new ( ) ;
80
86
static mut HOOK : Hook = Hook :: Default ;
81
87
@@ -180,7 +186,8 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
180
186
}
181
187
}
182
188
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.
184
191
///
185
192
/// [`take_hook`]: ./fn.take_hook.html
186
193
/// [`set_hook`]: ./fn.set_hook.html
@@ -189,16 +196,6 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
189
196
///
190
197
/// Panics if called from a panicking thread.
191
198
///
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
- ///
202
199
/// # Examples
203
200
///
204
201
/// 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> {
207
204
/// #![feature(panic_update_hook)]
208
205
/// use std::panic;
209
206
///
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);
215
216
/// });
216
217
///
217
218
/// panic!("Custom and then normal");
218
219
/// ```
219
220
#[ unstable( feature = "panic_update_hook" , issue = "92649" ) ]
220
221
pub fn update_hook < F > ( hook_fn : F )
221
222
where
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 ,
225
227
{
226
228
if thread:: panicking ( ) {
227
229
panic ! ( "cannot modify the panic hook from a panicking thread" ) ;
@@ -232,13 +234,12 @@ where
232
234
let old_hook = HOOK ;
233
235
HOOK = Hook :: Default ;
234
236
235
- let hook_for_fn = match old_hook {
237
+ let prev = match old_hook {
236
238
Hook :: Default => Box :: new ( default_hook) ,
237
239
Hook :: Custom ( ptr) => Box :: from_raw ( ptr) ,
238
240
} ;
239
241
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) ) ;
242
243
drop ( guard) ;
243
244
}
244
245
}
0 commit comments