From bd82113521abb7534b67645fe84b6b6790140c09 Mon Sep 17 00:00:00 2001 From: Aaron Loucks Date: Wed, 24 Apr 2019 00:07:40 -0400 Subject: [PATCH] Enable the default panic unwind hook to print backtraces again The default panic unwind hook attempts to print the backtrace by first initializing DbgHelp with `SymInitializeW`. The documentation states that this can't be called again until after `SymCleanup` is called first. If called prior to cleanup, it returns a non-success result. The default unwind hook detects this error and never tries to print the backtrace. This PR installs a new panic handler that first calls `SymCleanup` prior to calling the previously installed (or default) panic hook. Fixes #165 --- src/lib.rs | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f69a873b2..0ee145a96 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -187,10 +187,34 @@ unsafe fn dbghelp_init() { static mut INITIALIZED: bool = false; + #[cfg(feature = "std")] + fn dbghelp_init_cleanup() { + static SET_HOOK: std::sync::Once = std::sync::ONCE_INIT; + + let default_hook = std::panic::take_hook(); + + SET_HOOK.call_once(|| { + std::panic::set_hook(std::boxed::Box::new(move |panic_info| { + // The default unwind hook calls `SymInitializeW`, which will fail and prevent + // the panic backtrace from being printed if we do not first call `SymCleanup`. + unsafe { + INITIALIZED = false; + dbghelp::SymCleanup(processthreadsapi::GetCurrentProcess()); + } + default_hook(panic_info); + })) + }) + } + + #[cfg(not(feature = "std"))] + fn dbghelp_init_cleanup() {} + if !INITIALIZED { + INITIALIZED = true; + dbghelp::SymInitializeW(processthreadsapi::GetCurrentProcess(), 0 as *mut _, minwindef::TRUE); - INITIALIZED = true; + dbghelp_init_cleanup(); } -} +} \ No newline at end of file