Skip to content

Commit d6fff90

Browse files
committed
Fallback to the process handle in case DuplicateHandle fails
1 parent e86f4eb commit d6fff90

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

src/platform/dbghelp_utils.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,28 @@ namespace detail {
103103
// https://learn.microsoft.com/en-us/windows/win32/debug/initializing-the-symbol-handler
104104
// Apparently duplicating the process handle is the idiomatic thing to do and this avoids issues of
105105
// SymInitialize being called twice.
106-
// TODO: Fallback on failure
106+
// DuplicateHandle requires the PROCESS_DUP_HANDLE access right. If for some reason DuplicateHandle we fall back
107+
// to calling SymInitialize on the process handle.
108+
optional<DWORD> duplicate_handle_errored;
107109
if(!DuplicateHandle(proc, proc, proc, &duplicated_handle.get(), 0, FALSE, DUPLICATE_SAME_ACCESS)) {
108-
throw internal_error("DuplicateHandle failed{}", GetLastError());
110+
duplicate_handle_errored = GetLastError();
109111
}
110-
if(!SymInitialize(duplicated_handle.get(), NULL, TRUE)) {
111-
throw internal_error("SymInitialize failed{}", GetLastError());
112+
if(!SymInitialize(duplicate_handle_errored ? proc : duplicated_handle.get(), NULL, TRUE)) {
113+
if(duplicate_handle_errored) {
114+
throw internal_error(
115+
"SymInitialize failed with error code {} after DuplicateHandle failed with error code {}",
116+
GetLastError(),
117+
duplicate_handle_errored.unwrap()
118+
);
119+
} else {
120+
throw internal_error("SymInitialize failed with error code {}", GetLastError());
121+
}
112122
}
113123

114-
auto info = dbghelp_syminit_info::make_owned(exchange(duplicated_handle.get(), nullptr), true);
124+
auto info = dbghelp_syminit_info::make_owned(
125+
duplicate_handle_errored ? proc : exchange(duplicated_handle.get(), nullptr),
126+
duplicate_handle_errored ? false : true // looks funny but I think it's a little more expressive
127+
);
115128
// either cache and return a view or return the owning wrapper
116129
if(get_cache_mode() == cache_mode::prioritize_speed) {
117130
auto& syminit_cache = get_syminit_cache();

0 commit comments

Comments
 (0)