nagisa / rust_tracy_client

Tracy client libraries for Rust
Apache License 2.0
177 stars 36 forks source link

Fix stacktrace issues on Windows #122

Closed Timbals closed 3 weeks ago

Timbals commented 2 months ago

There are 2 issues with capturing stack traces on Windows. Specifically with the resolving of the symbols of the stack traces. Note that this affects both the stack traces captured by Rust and Tracy.

Both Rust and Tracy use the dbghelp.dll symbol helper to resolve symbols. The first issue is that dbghelp.dll is single threaded and all its functions need to be externally synchronized. Rust uses a named Windows mutex to synchronize access to dbghelp.dll between the standard library and the backtrace-rs crate when both are used. The first commit in this PR makes Tracy use the same named Mutex. Not properly synchronizing can lead to partially corrupted stacktraces.

Example corrupted stacktrace Note the `` at the top probably caused by some race condition ``` stack backtrace: 0: 0x7ff7a900767d - 1: 0x7ff7a9014bc9 - 2: 0x7ff7a9006011 - 3: 0x7ff7a90093c7 - 4: 0x7ff7a9008fb9 - 5: 0x7ff7a9009a72 - 6: 0x7ff7a900990f - 7: 0x7ff7a9007d6f - 8: 0x7ff7a9009526 - 9: 0x7ff7a903dbc4 - 10: 0x7ff7a90012ee - tracy_client_stacktrace::main at C:\Dev\tracy-client-stacktrace-issue\src\main.rs:5 11: 0x7ff7a900138b - core::ops::function::FnOnce::call_once > at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\core\src\ops\function.rs:250 12: 0x7ff7a900142e - core::hint::black_box at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\core\src\hint.rs:389 13: 0x7ff7a900142e - std::sys::backtrace::__rust_begin_short_backtrace > at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\std\src\sys\backtrace.rs:152 14: 0x7ff7a9001401 - std::rt::lang_start::closure$0 > at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\std\src\rt.rs:162 15: 0x7ff7a9004279 - std::rt::lang_start_internal::closure$2 at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\std\src\rt.rs:141 16: 0x7ff7a9004279 - std::panicking::try::do_call at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\std\src\panicking.rs:557 17: 0x7ff7a9004279 - std::panicking::try at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\std\src\panicking.rs:521 18: 0x7ff7a9004279 - std::panic::catch_unwind at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\std\src\panic.rs:350 19: 0x7ff7a9004279 - std::rt::lang_start_internal at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\std\src\rt.rs:141 20: 0x7ff7a90013da - std::rt::lang_start > at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\std\src\rt.rs:161 21: 0x7ff7a9001309 - main 22: 0x7ff7a903b918 - invoke_main at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78 23: 0x7ff7a903b918 - __scrt_common_main_seh at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288 24: 0x7ffaad70257d - BaseThreadInitThunk 25: 0x7ffaae1eaf28 - RtlUserThreadStart ```

The second issue is that Rust and Tracy initialize the symbol helper in different ways. Since Rust 1.78.0 the compiler no longer includes absolute paths to .pdb files in the binary (https://github.com/rust-lang/rust/pull/121297). That can make the symbol resolution fail because by default only the current working directory is searched for .pdb files. There was also a corresponding PR to backtrace-rs to include the executable location in the search path (https://github.com/rust-lang/backtrace-rs/pull/584), but when Tracy initializes dbghelp.dll first, the modules get loaded before the search path gets modified. The second commit in this PR fixes that by capturing and resolving a backtrace using the standard library before Tracy does the initialization. This fixes #101.

nagisa commented 3 weeks ago

Sorry for the delay! Will release 0.24.2 with this shortly.