summaryrefslogtreecommitdiff
path: root/src/dlls/dbgshim/dbgshim.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dlls/dbgshim/dbgshim.cpp')
-rw-r--r--src/dlls/dbgshim/dbgshim.cpp63
1 files changed, 52 insertions, 11 deletions
diff --git a/src/dlls/dbgshim/dbgshim.cpp b/src/dlls/dbgshim/dbgshim.cpp
index aeee778543..5f15cabe97 100644
--- a/src/dlls/dbgshim/dbgshim.cpp
+++ b/src/dlls/dbgshim/dbgshim.cpp
@@ -387,6 +387,19 @@ public:
return hr;
}
+ bool AreAllHandlesValid(HANDLE *handleArray, DWORD arrayLength)
+ {
+ for (int i = 0; i < (int)arrayLength; i++)
+ {
+ HANDLE h = handleArray[i];
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
HRESULT InternalEnumerateCLRs(HANDLE** ppHandleArray, _In_reads_(*pdwArrayLength) LPWSTR** ppStringArray, DWORD* pdwArrayLength)
{
int numTries = 0;
@@ -394,18 +407,46 @@ public:
while (numTries < 25)
{
+ hr = EnumerateCLRs(m_processId, ppHandleArray, ppStringArray, pdwArrayLength);
+
// EnumerateCLRs uses the OS API CreateToolhelp32Snapshot which can return ERROR_BAD_LENGTH or
// ERROR_PARTIAL_COPY. If we get either of those, we try wait 1/10th of a second try again (that
- // is the recommendation of the OS API owners)
- hr = EnumerateCLRs(m_processId, ppHandleArray, ppStringArray, pdwArrayLength);
+ // is the recommendation of the OS API owners).
if ((hr != HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY)) && (hr != HRESULT_FROM_WIN32(ERROR_BAD_LENGTH)))
{
- break;
+ // Just return any other error or if no handles were found (which means the coreclr module wasn't found yet).
+ if (FAILED(hr) || *ppHandleArray == NULL || *pdwArrayLength <= 0)
+ {
+ return hr;
+ }
+ // If EnumerateCLRs succeeded but any of the handles are INVALID_HANDLE_VALUE, then sleep and retry
+ // also. This fixes a race condition where dbgshim catches the coreclr module just being loaded but
+ // before g_hContinueStartupEvent has been initialized.
+ if (AreAllHandlesValid(*ppHandleArray, *pdwArrayLength))
+ {
+ return hr;
+ }
+ // Clean up memory allocated in EnumerateCLRs since this path it succeeded
+ CloseCLREnumeration(*ppHandleArray, *ppStringArray, *pdwArrayLength);
+
+ *ppHandleArray = NULL;
+ *ppStringArray = NULL;
+ *pdwArrayLength = 0;
}
+
+ // Sleep and retry enumerating the runtimes
Sleep(100);
numTries++;
+
+ if (m_canceled)
+ {
+ break;
+ }
}
+ // Indicate a timeout
+ hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
+
return hr;
}
@@ -517,9 +558,8 @@ public:
bool coreclrExists = false;
HRESULT hr = InvokeStartupCallback(&coreclrExists);
- // Because the target process is suspended on create, the toolhelp apis fail with the below errors even
- // with the retry logic in InternalEnumerateCLRs.
- if (SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY)) || (hr == HRESULT_FROM_WIN32(ERROR_BAD_LENGTH)))
+ // The retry logic in InternalEnumerateCLRs failed if ERROR_TIMEOUT was returned.
+ if (SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_TIMEOUT)))
{
if (!coreclrExists && !m_canceled)
{
@@ -531,8 +571,11 @@ public:
hr = InvokeStartupCallback(&coreclrExists);
if (SUCCEEDED(hr))
{
- // We should always find a coreclr module
- _ASSERTE(coreclrExists);
+ // We should always find a coreclr module so fail if we don't
+ if (!coreclrExists)
+ {
+ hr = E_FAIL;
+ }
}
}
}
@@ -1120,8 +1163,6 @@ EnumerateCLRs(
HANDLE hContinueStartupEvent = INVALID_HANDLE_VALUE;
HRESULT hr = GetContinueStartupEvent(debuggeePID, pStringArray[idx], &hContinueStartupEvent);
- _ASSERTE(SUCCEEDED(hr) == (hContinueStartupEvent != INVALID_HANDLE_VALUE));
-
pEventArray[idx] = hContinueStartupEvent;
#else
pEventArray[idx] = NULL;
@@ -1729,7 +1770,7 @@ GetContinueStartupEvent(
ThrowHR(E_FAIL);
}
- if (NULL != continueEvent)
+ if (NULL != continueEvent && INVALID_HANDLE_VALUE != continueEvent)
{
if (!DuplicateHandle(hProcess, continueEvent, GetCurrentProcess(), &continueEvent,
EVENT_MODIFY_STATE, FALSE, 0))