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:
parent
6689d14c20
commit
07d703a36b
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user