@@ -180,6 +180,69 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
180
180
}
181
181
}
182
182
183
+ /// Atomic combination of [`take_hook`] + [`set_hook`].
184
+ ///
185
+ /// [`take_hook`]: ./fn.take_hook.html
186
+ /// [`set_hook`]: ./fn.set_hook.html
187
+ ///
188
+ /// # Panics
189
+ ///
190
+ /// Panics if called from a panicking thread.
191
+ ///
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
+ /// # Examples
203
+ ///
204
+ /// The following will print the custom message, and then the normal output of panic.
205
+ ///
206
+ /// ```should_panic
207
+ /// #![feature(panic_update_hook)]
208
+ /// use std::panic;
209
+ ///
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
+ /// })
215
+ /// });
216
+ ///
217
+ /// panic!("Custom and then normal");
218
+ /// ```
219
+ #[ unstable( feature = "panic_update_hook" , issue = "92649" ) ]
220
+ pub fn update_hook < F > ( hook_fn : F )
221
+ where
222
+ F : FnOnce (
223
+ Box < dyn Fn ( & PanicInfo < ' _ > ) + ' static + Sync + Send > ,
224
+ ) -> Box < dyn Fn ( & PanicInfo < ' _ > ) + ' static + Sync + Send > ,
225
+ {
226
+ if thread:: panicking ( ) {
227
+ panic ! ( "cannot modify the panic hook from a panicking thread" ) ;
228
+ }
229
+
230
+ unsafe {
231
+ let guard = HOOK_LOCK . write ( ) ;
232
+ let old_hook = HOOK ;
233
+ HOOK = Hook :: Default ;
234
+
235
+ let hook_for_fn = match old_hook {
236
+ Hook :: Default => Box :: new ( default_hook) ,
237
+ Hook :: Custom ( ptr) => Box :: from_raw ( ptr) ,
238
+ } ;
239
+
240
+ let hook = hook_fn ( hook_for_fn) ;
241
+ HOOK = Hook :: Custom ( Box :: into_raw ( hook) ) ;
242
+ drop ( guard) ;
243
+ }
244
+ }
245
+
183
246
fn default_hook ( info : & PanicInfo < ' _ > ) {
184
247
// If this is a double panic, make sure that we print a backtrace
185
248
// for this panic. Otherwise only print it if logging is enabled.
0 commit comments