@@ -103,15 +103,28 @@ namespace detail {
103
103
// https://learn.microsoft.com/en-us/windows/win32/debug/initializing-the-symbol-handler
104
104
// Apparently duplicating the process handle is the idiomatic thing to do and this avoids issues of
105
105
// 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;
107
109
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 ();
109
111
}
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
+ }
112
122
}
113
123
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
+ );
115
128
// either cache and return a view or return the owning wrapper
116
129
if (get_cache_mode () == cache_mode::prioritize_speed) {
117
130
auto & syminit_cache = get_syminit_cache ();
0 commit comments