Duplicate process handle and use it for SymInitialize

https://learn.microsoft.com/en-us/windows/win32/debug/initializing-the-symbol-handler
This commit is contained in:
firesgc 2025-01-24 22:39:41 +01:00
parent 6689d14c20
commit 07d703a36b
3 changed files with 30 additions and 16 deletions

View File

@ -7,7 +7,7 @@
#include "utils/error.hpp"
#include "utils/microfmt.hpp"
#include <unordered_set>
#include <map>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
@ -19,20 +19,30 @@ namespace cpptrace {
namespace detail {
dbghelp_syminit_manager::~dbghelp_syminit_manager() {
for(auto handle : set) {
if(!SymCleanup(handle)) {
for(auto kvp : cache) {
if(!SymCleanup(kvp.second)) {
ASSERT(false, microfmt::format("Cpptrace SymCleanup failed with code {}\n", GetLastError()).c_str());
}
}
}
void dbghelp_syminit_manager::init(HANDLE proc) {
if(set.count(proc) == 0) {
HANDLE dbghelp_syminit_manager::init(HANDLE proc) {
auto itr = cache.find(proc);
if (itr != cache.end()) {
return itr->second;
}
HANDLE duplicatedHandle = nullptr;
if (!DuplicateHandle(proc, proc, proc, &duplicatedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
throw internal_error("DuplicateHandle failed");
}
if(!SymInitialize(proc, NULL, TRUE)) {
throw internal_error("SymInitialize failed {}", GetLastError());
}
set.insert(proc);
}
cache[proc] = duplicatedHandle;
return duplicatedHandle;
}
// Thread-safety: Must only be called from symbols_with_dbghelp while the dbghelp_lock lock is held

View File

@ -1,17 +1,17 @@
#ifndef DBGHELP_SYMINIT_MANAGER_HPP
#define DBGHELP_SYMINIT_MANAGER_HPP
#include <unordered_set>
#include <map>
namespace cpptrace {
namespace detail {
struct dbghelp_syminit_manager {
// The set below contains Windows `HANDLE` objects, `void*` is used to avoid
// including the (expensive) Windows header here
std::unordered_set<void*> set;
std::map<void*, void*> cache;
~dbghelp_syminit_manager();
void init(void* proc);
void* init(void* proc);
};
// Thread-safety: Must only be called from symbols_with_dbghelp while the dbghelp_lock lock is held

View File

@ -103,12 +103,16 @@ namespace detail {
// SymInitialize( GetCurrentProcess(), NULL, TRUE ) has
// already been called.
//
HANDLE duplicatedHandle = nullptr;
HANDLE proc = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
if(get_cache_mode() == cache_mode::prioritize_speed) {
get_syminit_manager().init(proc);
duplicatedHandle = get_syminit_manager().init(proc);
} else {
if(!SymInitialize(proc, NULL, TRUE)) {
if (!DuplicateHandle(proc, proc, proc, &duplicatedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
throw internal_error("DuplicateHandle failed");
}
if(!SymInitialize(duplicatedHandle, NULL, TRUE)) {
throw internal_error("SymInitialize failed");
}
}
@ -116,7 +120,7 @@ namespace detail {
if(
!StackWalk64(
machine_type,
proc,
duplicatedHandle,
thread,
&frame,
machine_type == IMAGE_FILE_MACHINE_I386 ? NULL : &context,
@ -145,7 +149,7 @@ namespace detail {
}
}
if(get_cache_mode() != cache_mode::prioritize_speed) {
if(!SymCleanup(proc)) {
if(!SymCleanup(duplicatedHandle)) {
throw internal_error("SymCleanup failed");
}
}