diff options
author | dotnet-bot <dotnet-bot@microsoft.com> | 2015-05-06 23:43:46 -0700 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2015-05-07 12:03:00 -0700 |
commit | 484a2cf0b0c4e304a5093ec26e07fe41f8896c3c (patch) | |
tree | 348b56df4cdb235bb87ba9bc9118711c8db13bfd /src/vm/dwreport.cpp | |
parent | c6efc7047edb38075310cfef8ea28b91717b8108 (diff) | |
download | coreclr-484a2cf0b0c4e304a5093ec26e07fe41f8896c3c.tar.gz coreclr-484a2cf0b0c4e304a5093ec26e07fe41f8896c3c.tar.bz2 coreclr-484a2cf0b0c4e304a5093ec26e07fe41f8896c3c.zip |
Merge changes from parent branch
[tfs-changeset: 1466545]
Diffstat (limited to 'src/vm/dwreport.cpp')
-rw-r--r-- | src/vm/dwreport.cpp | 98 |
1 files changed, 61 insertions, 37 deletions
diff --git a/src/vm/dwreport.cpp b/src/vm/dwreport.cpp index 210e08240c..ccf41ea953 100644 --- a/src/vm/dwreport.cpp +++ b/src/vm/dwreport.cpp @@ -2776,52 +2776,71 @@ DWORD WINAPI DoFaultReportWorkerCallback(LPVOID pParam) } EX_END_CATCH(SwallowAllExceptions); } - - SetupThread(); - - GCX_COOP(); - if (pData->pThread != NULL && pExceptionInfo != NULL && - pExceptionInfo->ContextRecord == NULL && - pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW && - pExceptionInfo->ExceptionRecord->ExceptionAddress == 0) + // The purpose of the loop below is to avoid deadlocks during the abnormal process termination. + // We will try to acquire the lock for 100 times to see whether we can successfully grap it. If we + // can, then we can setup the thread and report the fault without worrying about the deadlock. + // Otherwise we won't report the fault. It's still possible that we can enter the critical section + // and report the fault without having deadlocks after this spin, but compared to the risky of + // having deadlock, we still prefer not to report the fault if we can't get the lock after spin. + BOOL isThreadSetup = false; + for (int i = 0; i < 100; i++) + { + if (ThreadStore::CanAcquireLock()) + { + SetupThread(); + isThreadSetup = true; + break; + } + __SwitchToThread(30, CALLER_LIMITS_SPINNING); + } + + if (isThreadSetup) { - // In the case of a soft SO on a managed thread, we set the ExceptionAddress to one of the following - // - // 1. The first method on the stack that is in a non-system module. - // 2. Failing that, the first method on the stack that is in a system module + GCX_COOP(); + + if (pData->pThread != NULL && pExceptionInfo != NULL && + pExceptionInfo->ContextRecord == NULL && + pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW && + pExceptionInfo->ExceptionRecord->ExceptionAddress == 0) + { + // In the case of a soft SO on a managed thread, we set the ExceptionAddress to one of the following + // + // 1. The first method on the stack that is in a non-system module. + // 2. Failing that, the first method on the stack that is in a system module - CONTEXT ContextRecord; - memset(&ContextRecord, 0, sizeof(CONTEXT)); + CONTEXT ContextRecord; + memset(&ContextRecord, 0, sizeof(CONTEXT)); - ExceptionInfo.ContextRecord = &ContextRecord; // To display the "Send" button, dw20 wants a non-NULL pointer - ExceptionRecord = *(pExceptionInfo->ExceptionRecord); - ExceptionInfo.ExceptionRecord = &ExceptionRecord; - pExceptionInfo = &ExceptionInfo; + ExceptionInfo.ContextRecord = &ContextRecord; // To display the "Send" button, dw20 wants a non-NULL pointer + ExceptionRecord = *(pExceptionInfo->ExceptionRecord); + ExceptionInfo.ExceptionRecord = &ExceptionRecord; + pExceptionInfo = &ExceptionInfo; - WatsonSOExceptionAddress WatsonExceptionAddresses; + WatsonSOExceptionAddress WatsonExceptionAddresses; - pData->pThread->StackWalkFrames( - WatsonSOStackCrawlCallback, - &WatsonExceptionAddresses, - FUNCTIONSONLY|ALLOW_ASYNC_STACK_WALK); + pData->pThread->StackWalkFrames( + WatsonSOStackCrawlCallback, + &WatsonExceptionAddresses, + FUNCTIONSONLY|ALLOW_ASYNC_STACK_WALK); - if (WatsonExceptionAddresses.m_UserMethod != NULL) - { - pExceptionInfo->ExceptionRecord->ExceptionAddress = WatsonExceptionAddresses.m_UserMethod; - } - else if (WatsonExceptionAddresses.m_SystemMethod != NULL) - { - pExceptionInfo->ExceptionRecord->ExceptionAddress = WatsonExceptionAddresses.m_SystemMethod; - } + if (WatsonExceptionAddresses.m_UserMethod != NULL) + { + pExceptionInfo->ExceptionRecord->ExceptionAddress = WatsonExceptionAddresses.m_UserMethod; + } + else if (WatsonExceptionAddresses.m_SystemMethod != NULL) + { + pExceptionInfo->ExceptionRecord->ExceptionAddress = WatsonExceptionAddresses.m_SystemMethod; + } - } + } - pData->result = DoFaultReportWorker( - pExceptionInfo, - pData->tore, - pData->pThread, - pData->dwThreadID); + pData->result = DoFaultReportWorker( + pExceptionInfo, + pData->tore, + pData->pThread, + pData->dwThreadID); + } return 0; @@ -3162,6 +3181,11 @@ FaultReportResult DoFaultReport( // Was Watson attempted, successful? GCX_PREEMP(); if (!g_pDebugInterface || + // When GC is in progress and current thread is either a GC thread or a managed + // thread under Coop mode, this will let the new generated DoFaultReportCallBack + // thread trigger a deadlock. So in this case, we should directly abort the fault + // report to avoid the deadlock. + ((IsGCThread() || pThread->PreemptiveGCDisabled()) && GCHeap::IsGCInProgress()) || FAILED(g_pDebugInterface->RequestFavor(DoFaultReportFavorWorker, pData))) { // If we can't initialize the debugger helper thread or we are running on the debugger helper |