1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
7 // ---------------------------------------------------------------------------
9 // ---------------------------------------------------------------------------
15 #include "dbginterface.h"
16 #include "eemessagebox.h"
18 #include "eventreporter.h"
19 #include "finalizerthread.h"
20 #include "threadsuspend.h"
24 #endif // !FEATURE_PAL
26 #include "eventtrace.h"
29 BYTE g_EEPolicyInstance[sizeof(EEPolicy)];
34 new (g_EEPolicyInstance) EEPolicy();
47 for (n = 0; n < MaxClrOperation; n++) {
48 m_Timeout[n] = INFINITE;
49 m_ActionOnTimeout[n] = eNoAction;
50 m_DefaultAction[n] = eNoAction;
52 m_Timeout[OPR_ProcessExit] = 40000;
53 m_ActionOnTimeout[OPR_ProcessExit] = eRudeExitProcess;
54 m_ActionOnTimeout[OPR_ThreadAbort] = eAbortThread;
55 m_ActionOnTimeout[OPR_ThreadRudeAbortInNonCriticalRegion] = eRudeAbortThread;
56 m_ActionOnTimeout[OPR_ThreadRudeAbortInCriticalRegion] = eRudeAbortThread;
58 m_DefaultAction[OPR_ThreadAbort] = eAbortThread;
59 m_DefaultAction[OPR_ThreadRudeAbortInNonCriticalRegion] = eRudeAbortThread;
60 m_DefaultAction[OPR_ThreadRudeAbortInCriticalRegion] = eRudeAbortThread;
61 m_DefaultAction[OPR_AppDomainUnload] = eUnloadAppDomain;
62 m_DefaultAction[OPR_AppDomainRudeUnload] = eRudeUnloadAppDomain;
63 m_DefaultAction[OPR_ProcessExit] = eExitProcess;
64 m_DefaultAction[OPR_FinalizerRun] = eNoAction;
66 for (n = 0; n < MaxClrFailure; n++) {
67 m_ActionOnFailure[n] = eNoAction;
69 m_ActionOnFailure[FAIL_CriticalResource] = eThrowException;
70 m_ActionOnFailure[FAIL_NonCriticalResource] = eThrowException;
71 m_ActionOnFailure[FAIL_OrphanedLock] = eNoAction;
72 m_ActionOnFailure[FAIL_FatalRuntime] = eRudeExitProcess;
73 #ifdef FEATURE_CORECLR
74 // For CoreCLR, initialize the default action for AV processing to all
75 // all kind of code to catch AV exception. If the host wants, they can
76 // specify a different action for this.
77 m_ActionOnFailure[FAIL_AccessViolation] = eNoAction;
78 #endif // FEATURE_CORECLR
79 m_ActionOnFailure[FAIL_StackOverflow] = eRudeExitProcess;
80 m_ActionOnFailure[FAIL_CodeContract] = eThrowException;
81 m_unhandledExceptionPolicy = eRuntimeDeterminedPolicy;
84 BOOL EEPolicy::IsValidActionForOperation(EClrOperation operation, EPolicyAction action)
95 return action >= eAbortThread &&
96 action < MaxPolicyAction;
97 case OPR_ThreadRudeAbortInNonCriticalRegion:
98 case OPR_ThreadRudeAbortInCriticalRegion:
99 return action >= eRudeAbortThread && action != eUnloadAppDomain &&
100 action < MaxPolicyAction;
101 case OPR_AppDomainUnload:
102 return action >= eUnloadAppDomain &&
103 action < MaxPolicyAction;
104 case OPR_AppDomainRudeUnload:
105 return action >= eRudeUnloadAppDomain &&
106 action < MaxPolicyAction;
107 case OPR_ProcessExit:
108 return action >= eExitProcess &&
109 action < MaxPolicyAction;
110 case OPR_FinalizerRun:
111 return action == eNoAction ||
112 (action >= eAbortThread &&
113 action < MaxPolicyAction);
115 _ASSERT (!"Do not know valid action for this operation");
121 BOOL EEPolicy::IsValidActionForTimeout(EClrOperation operation, EPolicyAction action)
131 case OPR_ThreadAbort:
132 return action > eAbortThread &&
133 action < MaxPolicyAction;
134 case OPR_ThreadRudeAbortInNonCriticalRegion:
135 case OPR_ThreadRudeAbortInCriticalRegion:
136 return action > eRudeUnloadAppDomain &&
137 action < MaxPolicyAction;
138 case OPR_AppDomainUnload:
139 return action > eUnloadAppDomain &&
140 action < MaxPolicyAction;
141 case OPR_AppDomainRudeUnload:
142 return action > eRudeUnloadAppDomain &&
143 action < MaxPolicyAction;
144 case OPR_ProcessExit:
145 return action > eExitProcess &&
146 action < MaxPolicyAction;
147 case OPR_FinalizerRun:
148 return action == eNoAction ||
149 (action >= eAbortThread &&
150 action < MaxPolicyAction);
152 _ASSERT (!"Do not know valid action for this operation");
158 BOOL EEPolicy::IsValidActionForFailure(EClrFailure failure, EPolicyAction action)
168 case FAIL_NonCriticalResource:
169 return action >= eThrowException &&
170 action < MaxPolicyAction;
171 case FAIL_CriticalResource:
172 return action >= eThrowException &&
173 action < MaxPolicyAction;
174 case FAIL_FatalRuntime:
175 return action >= eRudeExitProcess &&
176 action < MaxPolicyAction;
177 case FAIL_OrphanedLock:
178 return action >= eUnloadAppDomain &&
179 action < MaxPolicyAction;
180 case FAIL_AccessViolation:
181 #ifdef FEATURE_CORECLR
182 // Allowed actions on failure are:
184 // eNoAction or eRudeExitProcess.
185 return ((action == eNoAction) || (action == eRudeExitProcess));
186 #else // !FEATURE_CORECLR
187 // FAIL_AccessViolation is defined for the desktop so that
188 // if any more definitions are added after it, their value
189 // should remain constant irrespective of whether its the
190 // desktop CLR or CoreCLR.
192 // That said, currently, Desktop CLR does not support
193 // FAIL_AccessViolation. Thus, any calls which use
194 // this failure are not allowed.
196 #endif // FEATURE_CORECLR
197 case FAIL_StackOverflow:
198 return action >= eRudeUnloadAppDomain &&
199 action < MaxPolicyAction;
200 case FAIL_CodeContract:
201 return action >= eThrowException &&
202 action <= eExitProcess;
204 _ASSERTE (!"Do not know valid action for this failure");
211 HRESULT EEPolicy::SetTimeout(EClrOperation operation, DWORD timeout)
221 if (static_cast<UINT>(operation) < MaxClrOperation)
223 m_Timeout[operation] = timeout;
224 if (operation == OPR_FinalizerRun &&
227 FastInterlockOr((DWORD*)&g_FinalizerWaiterStatus, FWS_WaitInterrupt);
228 FinalizerThread::SignalFinalizationDone(FALSE);
238 HRESULT EEPolicy::SetActionOnTimeout(EClrOperation operation, EPolicyAction action)
247 if (static_cast<UINT>(operation) < MaxClrOperation &&
248 IsValidActionForTimeout(operation, action))
250 m_ActionOnTimeout[operation] = action;
259 EPolicyAction EEPolicy::GetFinalAction(EPolicyAction action, Thread *pThread)
261 LIMITED_METHOD_CONTRACT;
262 _ASSERTE(static_cast<UINT>(action) < MaxPolicyAction);
264 if (action < eAbortThread || action > eFastExitProcess)
271 // Look at default action. If the default action is more severe,
272 // use the default action instead.
273 EPolicyAction defaultAction = action;
277 defaultAction = m_DefaultAction[OPR_ThreadAbort];
279 case eRudeAbortThread:
280 if (pThread && !pThread->HasLockInCurrentDomain())
282 defaultAction = m_DefaultAction[OPR_ThreadRudeAbortInNonCriticalRegion];
286 defaultAction = m_DefaultAction[OPR_ThreadRudeAbortInCriticalRegion];
289 case eUnloadAppDomain:
290 defaultAction = m_DefaultAction[OPR_AppDomainUnload];
292 case eRudeUnloadAppDomain:
293 defaultAction = m_DefaultAction[OPR_AppDomainRudeUnload];
296 case eFastExitProcess:
297 defaultAction = m_DefaultAction[OPR_ProcessExit];
298 if (defaultAction < action)
300 defaultAction = action;
306 _ASSERTE(static_cast<UINT>(defaultAction) < MaxPolicyAction);
308 if (defaultAction == action)
313 _ASSERTE(defaultAction > action);
314 action = defaultAction;
318 // Allow setting timeout and action in one call.
319 // If we decide to have atomical operation on Policy, we can use lock here
320 // while SetTimeout and SetActionOnTimeout can not.
321 HRESULT EEPolicy::SetTimeoutAndAction(EClrOperation operation, DWORD timeout, EPolicyAction action)
330 if (static_cast<UINT>(operation) < MaxClrOperation &&
331 IsValidActionForTimeout(operation, action))
333 m_ActionOnTimeout[operation] = action;
334 m_Timeout[operation] = timeout;
335 if (operation == OPR_FinalizerRun &&
338 FastInterlockOr((DWORD*)&g_FinalizerWaiterStatus, FWS_WaitInterrupt);
339 FinalizerThread::SignalFinalizationDone(FALSE);
349 HRESULT EEPolicy::SetDefaultAction(EClrOperation operation, EPolicyAction action)
358 if (static_cast<UINT>(operation) < MaxClrOperation &&
359 IsValidActionForOperation(operation, action))
361 m_DefaultAction[operation] = action;
370 HRESULT EEPolicy::SetActionOnFailure(EClrFailure failure, EPolicyAction action)
379 if (static_cast<UINT>(failure) < MaxClrFailure &&
380 IsValidActionForFailure(failure, action))
382 m_ActionOnFailure[failure] = action;
391 EPolicyAction EEPolicy::GetActionOnFailureNoHostNotification(EClrFailure failure)
401 _ASSERTE (failure < MaxClrFailure);
402 if (failure == FAIL_StackOverflow)
404 return m_ActionOnFailure[failure];
407 return GetFinalAction(m_ActionOnFailure[failure], GetThread());
410 EPolicyAction EEPolicy::GetActionOnFailure(EClrFailure failure)
420 _ASSERTE(static_cast<UINT>(failure) < MaxClrFailure);
421 if (failure == FAIL_StackOverflow)
423 return m_ActionOnFailure[failure];
426 EPolicyAction finalAction = GetActionOnFailureNoHostNotification(failure);
427 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
428 IHostPolicyManager *pHostPolicyManager = CorHost2::GetHostPolicyManager();
429 if (pHostPolicyManager)
432 Thread* pThread = GetThread();
435 pThread->AddFiberInfo(Thread::ThreadTrackInfo_Escalation);
438 BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
439 pHostPolicyManager->OnFailure(failure, finalAction);
440 END_SO_TOLERANT_CODE_CALLING_HOST;
442 #endif // FEATURE_INCLUDE_ALL_INTERFACES
447 void EEPolicy::NotifyHostOnTimeout(EClrOperation operation, EPolicyAction action)
458 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
459 IHostPolicyManager *pHostPolicyManager = CorHost2::GetHostPolicyManager();
460 if (pHostPolicyManager)
463 Thread* pThread = GetThread();
466 pThread->AddFiberInfo(Thread::ThreadTrackInfo_Escalation);
469 BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
470 pHostPolicyManager->OnTimeout(operation, action);
471 END_SO_TOLERANT_CODE_CALLING_HOST;
473 #endif // FEATURE_INCLUDE_ALL_INTERFACES
477 void EEPolicy::NotifyHostOnDefaultAction(EClrOperation operation, EPolicyAction action)
488 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
489 IHostPolicyManager *pHostPolicyManager = CorHost2::GetHostPolicyManager();
490 if (pHostPolicyManager)
493 Thread* pThread = GetThread();
496 pThread->AddFiberInfo(Thread::ThreadTrackInfo_Escalation);
499 BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
500 pHostPolicyManager->OnDefaultAction(operation, action);
501 END_SO_TOLERANT_CODE_CALLING_HOST;
503 #endif // FEATURE_INCLUDE_ALL_INTERFACES
506 void SafeExitProcess(UINT exitCode, BOOL fAbort = FALSE, ShutdownCompleteAction sca = SCA_ExitProcessWhenShutdownComplete)
508 // The process is shutting down. No need to check SO contract.
509 SO_NOT_MAINLINE_FUNCTION;
510 STRESS_LOG2(LF_SYNC, LL_INFO10, "SafeExitProcess: exitCode = %d, fAbort = %d\n", exitCode, fAbort);
513 DISABLED(GC_TRIGGERS);
518 // The runtime must be in the appropriate thread mode when we exit, so that we
519 // aren't surprised by the thread mode when our DLL_PROCESS_DETACH occurs, or when
520 // other DLLs call Release() on us in their detach [dangerous!], etc.
521 GCX_PREEMP_NO_DTOR();
523 FastInterlockExchange((LONG*)&g_fForbidEnterEE, TRUE);
525 ProcessEventForHost(Event_ClrDisabled, NULL);
527 // Note that for free and retail builds StressLog must also be enabled
528 if (g_pConfig && g_pConfig->StressLog())
530 if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_BreakOnBadExit))
532 // Workaround for aspnet
533 PathString wszFilename;
534 bool bShouldAssert = true;
535 if (WszGetModuleFileName(NULL, wszFilename))
537 wszFilename.LowerCase();
539 if (wcsstr(wszFilename, W("aspnet_compiler")))
541 bShouldAssert = false;
545 unsigned goodExit = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_SuccessExit);
546 if (bShouldAssert && exitCode != goodExit)
548 _ASSERTE(!"Bad Exit value");
549 FAULT_NOT_FATAL(); // if we OOM we can simply give up
550 SetErrorMode(0); // Insure that we actually cause the messsage box to pop.
551 EEMessageBoxCatastrophic(IDS_EE_ERRORMESSAGETEMPLATE, IDS_EE_ERRORTITLE, exitCode, W("BreakOnBadExit: returning bad exit code"));
556 // If we call ExitProcess, other threads will be torn down
557 // so we don't get to debug their state. Stop this!
560 _ASSERTE(!"In SafeExitProcess: An assert was hit on some other thread");
563 // Turn off exception processing, because if some other random DLL has a
564 // fault in DLL_PROCESS_DETACH, we could get called for exception handling.
565 // Since we've turned off part of the runtime, we can't, for instance,
566 // properly execute the GC that handling an exception might trigger.
567 g_fNoExceptions = true;
568 LOG((LF_EH, LL_INFO10, "SafeExitProcess: turning off exceptions\n"));
570 if (sca == SCA_ExitProcessWhenShutdownComplete)
572 // disabled because if we fault in this code path we will trigger our
573 // Watson code via EntryPointFilter which is THROWS (see Dev11 317016)
574 CONTRACT_VIOLATION(ThrowsViolation);
579 TerminateProcess(GetCurrentProcess(), exitCode);
583 EEPolicy::ExitProcessViaShim(exitCode);
587 // This is a helper to exit the process after coordinating with the shim. It is used by
588 // SafeExitProcess above, as well as from CorHost2::ExitProcess when we know that we must
589 // exit the process without doing further work to shutdown this runtime. This first attempts
590 // to call back to the Shim to shutdown any other runtimes within the process.
592 // IMPORTANT NOTE: exercise extreme caution when adding new calls to this method. It is highly
593 // likely that you want to call SafeExitProcess, or EEPolicy::HandleExitProcess instead of this.
594 // This function only exists to factor some common code out of the methods mentioned above.
597 void EEPolicy::ExitProcessViaShim(UINT exitCode)
599 LIMITED_METHOD_CONTRACT;
601 // We must call back to the Shim in order to exit the process, as this may be just one
602 // runtime in a process with many. We need to give the other runtimes a chance to exit
603 // cleanly. If we can't make the call, or if the call fails for some reason, then we
604 // simply exit the process here, which is rude to the others, but the best we can do.
605 #if !defined(FEATURE_CORECLR)
607 ReleaseHolder<ICLRRuntimeHostInternal> pRuntimeHostInternal;
609 HRESULT hr = g_pCLRRuntime->GetInterface(CLSID_CLRRuntimeHostInternal,
610 IID_ICLRRuntimeHostInternal,
611 &pRuntimeHostInternal);
615 pRuntimeHostInternal->ShutdownAllRuntimesThenExit(exitCode);
616 LOG((LF_EH, LL_INFO10, "ExitProcessViaShim: shim returned... exiting now.\n"));
619 #endif // !FEATURE_CORECLR
621 ExitProcess(exitCode);
625 //---------------------------------------------------------------------------------------
626 // DisableRuntime disables this runtime, suspending all managed execution and preventing
627 // threads from entering the runtime. This will cause the caller to block forever as well
628 // unless sca is SCA_ReturnWhenShutdownComplete.
629 //---------------------------------------------------------------------------------------
630 void DisableRuntime(ShutdownCompleteAction sca)
634 DISABLED(GC_TRIGGERS);
639 FastInterlockExchange((LONG*)&g_fForbidEnterEE, TRUE);
641 if (!g_fSuspendOnShutdown)
645 if (ThreadStore::HoldingThreadStore(GetThread()))
647 ThreadSuspend::UnlockThreadStore();
649 ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_SHUTDOWN);
652 if (!g_fSuspendOnShutdown)
654 ThreadStore::TrapReturningThreads(TRUE);
655 g_fSuspendOnShutdown = TRUE;
656 ClrFlsSetThreadType(ThreadType_Shutdown);
659 // Don't restart runtime. CLR is disabled.
662 GCX_PREEMP_NO_DTOR();
664 ProcessEventForHost(Event_ClrDisabled, NULL);
665 ClrFlsClearThreadType(ThreadType_Shutdown);
667 if (g_pDebugInterface != NULL)
669 g_pDebugInterface->DisableDebugger();
672 if (sca == SCA_ExitProcessWhenShutdownComplete)
674 __SwitchToThread(INFINITE, CALLER_LIMITS_SPINNING);
675 _ASSERTE (!"Should not reach here");
680 //---------------------------------------------------------------------------------------
681 // HandleExitProcessHelper is used to shutdown the runtime as specified by the given
682 // action, then to exit the process. Note, however, that the process will not exit if
683 // sca is SCA_ReturnWhenShutdownComplete. In that case, this method will simply return after
684 // performing the shutdown actions.
685 //---------------------------------------------------------------------------------------
687 // If g_fFastExitProcess is 0, normal shutdown
688 // If g_fFastExitProcess is 1, fast shutdown. Only doing log.
689 // If g_fFastExitProcess is 2, do not run EEShutDown.
690 DWORD g_fFastExitProcess = 0;
692 extern void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading);
694 static void HandleExitProcessHelper(EPolicyAction action, UINT exitCode, ShutdownCompleteAction sca)
699 case eFastExitProcess:
700 g_fFastExitProcess = 1;
708 exitCode = GetLatchedExitCode();
710 SafeExitProcess(exitCode, FALSE, sca);
712 case eRudeExitProcess:
713 g_fFastExitProcess = 2;
714 SafeExitProcess(exitCode, TRUE, sca);
716 case eDisableRuntime:
720 _ASSERTE (!"Invalid policy");
726 EPolicyAction EEPolicy::DetermineResourceConstraintAction(Thread *pThread)
737 EPolicyAction action;
738 if (pThread->HasLockInCurrentDomain()) {
739 action = GetEEPolicy()->GetActionOnFailure(FAIL_CriticalResource);
742 action = GetEEPolicy()->GetActionOnFailure(FAIL_NonCriticalResource);
744 AppDomain *pDomain = GetAppDomain();
745 // If it is default domain, we can not unload the appdomain
746 if (pDomain == SystemDomain::System()->DefaultDomain() &&
747 (action == eUnloadAppDomain || action == eRudeUnloadAppDomain))
749 action = eThrowException;
751 // If the current thread is AD unload helper thread, it should not block itself.
752 else if (pThread->HasThreadStateNC(Thread::TSNC_ADUnloadHelper) &&
753 action < eExitProcess)
755 action = eThrowException;
761 void EEPolicy::PerformADUnloadAction(EPolicyAction action, BOOL haveStack, BOOL forStackOverflow)
763 STATIC_CONTRACT_THROWS;
764 STATIC_CONTRACT_GC_TRIGGERS;
765 STATIC_CONTRACT_MODE_COOPERATIVE;
767 STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::PerformADUnloadAction\n");
769 Thread *pThread = GetThread();
771 AppDomain *pDomain = GetAppDomain();
773 if (!IsFinalizerThread())
776 Frame *pFrame = pThread->GetFirstTransitionInto(GetAppDomain(), &count);
778 pThread->SetUnloadBoundaryFrame(pFrame);
782 pDomain->EnableADUnloadWorker(action==eUnloadAppDomain? ADU_Safe : ADU_Rude);
783 // Can't perform a join when we are handling a true SO. We need to enable the unload woker but let the thread continue running
784 // through EH processing so that we can recover the stack and reset the guard page.
787 pThread->SetAbortRequest(action==eUnloadAppDomain? EEPolicy::TA_V1Compatible : EEPolicy::TA_Rude);
788 if (forStackOverflow)
790 OBJECTREF exceptObj = CLRException::GetPreallocatedRudeThreadAbortException();
791 pThread->SetAbortInitiated();
792 RaiseTheExceptionInternalOnly(exceptObj, FALSE, TRUE);
795 OBJECTREF exceptObj = CLRException::GetPreallocatedThreadAbortException();
796 pThread->SetAbortInitiated();
797 RaiseTheExceptionInternalOnly(exceptObj, FALSE, FALSE);
801 void EEPolicy::PerformResourceConstraintAction(Thread *pThread, EPolicyAction action, UINT exitCode, BOOL haveStack)
805 _ASSERTE(GetAppDomain() != NULL);
808 case eThrowException:
809 // Caller is going to rethrow.
813 pThread->UserAbort(Thread::TAR_Thread, TA_Safe, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
815 case eRudeAbortThread:
816 pThread->UserAbort(Thread::TAR_Thread, TA_Rude, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
818 case eUnloadAppDomain:
819 case eRudeUnloadAppDomain:
822 PerformADUnloadAction(action,haveStack);
826 case eFastExitProcess:
827 case eRudeExitProcess:
828 case eDisableRuntime:
829 HandleExitProcessFromEscalation(action, exitCode);
832 _ASSERTE (!"Invalid policy");
837 void EEPolicy::HandleOutOfMemory()
841 _ASSERTE (g_pOutOfMemoryExceptionClass);
843 Thread *pThread = GetThread();
846 EPolicyAction action = DetermineResourceConstraintAction(pThread);
848 // Check if we are executing in the context of a Constrained Execution Region.
849 if (action != eThrowException && Thread::IsExecutingWithinCer())
851 // Hitting OOM in a CER region should throw the OOM without regard to the escalation policy
852 // since the CER author has declared they are hardened against such failures. That's
853 // the whole point of CERs, to denote regions where code knows exactly how to deal with
854 // failures in an attempt to minimize the need for rollback or recycling.
858 PerformResourceConstraintAction(pThread, action, HOST_E_EXITPROCESS_OUTOFMEMORY, TRUE);
861 #ifdef FEATURE_STACK_PROBE
862 //---------------------------------------------------------------------------------------
864 // IsSOTolerant - Is the current thread in SO Tolerant region?
867 // pLimitFrame: the limit of search for frames
870 // TRUE if in SO tolerant region.
871 // FALSE if in SO intolerant region.
874 // We walk our frame chain to decide. If HelperMethodFrame is seen first, we are in tolerant
875 // region. If EnterSOIntolerantCodeFrame is seen first, we are in intolerant region.
877 BOOL Thread::IsSOTolerant(void * pLimitFrame)
879 LIMITED_METHOD_CONTRACT;
881 Frame *pFrame = GetFrame();
882 void* pSOIntolerantMarker = ClrFlsGetValue(TlsIdx_SOIntolerantTransitionHandler);
883 if (pSOIntolerantMarker == FRAME_TOP)
885 // We have not set a marker for intolerant transition yet.
888 while (pFrame != FRAME_TOP && pFrame < pLimitFrame)
890 Frame::ETransitionType type = pFrame->GetTransitionType();
891 if (pFrame > pSOIntolerantMarker)
895 else if (type == Frame::TT_M2U || type == Frame::TT_InternalCall ||
896 // We can not call HelperMethodFrame::GetFunction on SO since the call
897 // may need to call into host. This is why we check for TT_InternalCall first.
898 pFrame->GetFunction() != NULL)
902 pFrame = pFrame->Next();
905 if (pFrame == FRAME_TOP)
906 // We walked to the end of chain, but the thread has one IntolerantMarker on stack decided from
907 // the check above while loop.
915 //---------------------------------------------------------------------------------------
917 // EEPolicy::HandleStackOverflow - Handle stack overflow according to policy
921 // pLimitFrame: the limit of search for frames in order to decide if in SO tolerant
926 // How is stack overflow handled?
927 // If stack overflows in non-hosted case, we terminate the process.
928 // For hosted case with escalation policy
929 // 1. If stack overflows in managed code, or in VM before switching to SO intolerant region, and the GC mode is Cooperative
930 // the domain is rudely unloaded, or the process is terminated if the current domain is default domain.
931 // a. This action is done through BEGIN_SO_TOLERANT_CODE if there is one.
932 // b. If there is not this macro on the stack, we mark the domain being unload requested, and when the thread
933 // dies or is recycled, we finish the AD unload.
934 // 2. If stack overflows in SO tolerant region, but the GC mode is Preemptive, the process is killed in vector handler, or our
935 // managed exception handler (COMPlusFrameHandler or ProcessCLRException).
936 // 3. If stack overflows in SO intolerant region, the process is killed as soon as the exception is seen by our vector handler, or
937 // our managed exception handler.
939 // If SO Probing code is disabled (by FEATURE_STACK_PROBE not defined) then the process
940 // is terminated if there is StackOverflow as all clr code will be considered SO Intolerant.
941 void EEPolicy::HandleStackOverflow(StackOverflowDetector detector, void * pLimitFrame)
945 STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleStackOverflow\n");
947 Thread *pThread = GetThread();
951 //_ASSERTE (detector != SOD_ManagedFrameHandler);
952 // ProcessSOEventForHost(NULL, FALSE);
954 // For security reason, it is not safe to continue execution if stack overflow happens
955 // unless a host tells us to do something different.
956 // EEPolicy::HandleFatalStackOverflow(NULL);
960 #ifdef FEATURE_STACK_PROBE
962 // We only process SO once at
963 // 1. VectoredExceptionHandler if SO in mscorwks
964 // 2. managed exception handler
965 // 3. SO_Tolerant transition handler
966 if (pThread->HasThreadStateNC(Thread::TSNC_SOWorkNeeded) &&
967 detector != SOD_UnmanagedFrameHandler)
973 #ifdef FEATURE_STACK_PROBE
974 BOOL fInSoTolerant = pThread->IsSOTolerant(pLimitFrame);
976 BOOL fInSoTolerant = false;
979 EXCEPTION_POINTERS exceptionInfo;
980 GetCurrentExceptionPointers(&exceptionInfo);
982 _ASSERTE(exceptionInfo.ExceptionRecord);
984 #ifdef FEATURE_STACK_PROBE
985 DWORD exceptionCode = exceptionInfo.ExceptionRecord->ExceptionCode;
987 AppDomain *pCurrentDomain = ::GetAppDomain();
988 BOOL fInDefaultDomain = (pCurrentDomain == SystemDomain::System()->DefaultDomain());
989 BOOL fInCLR = IsIPInModule(g_pMSCorEE, (PCODE)GetIP(exceptionInfo.ContextRecord));
991 if (exceptionCode == EXCEPTION_SOFTSO)
993 // Our probe detects a thread does not have enough stack. But we have not trashed the process
995 fInSoTolerant = TRUE;
999 _ASSERTE (exceptionCode == STATUS_STACK_OVERFLOW);
1003 case SOD_ManagedFrameHandler:
1004 if (!pThread->PreemptiveGCDisabled() && !fInCLR && fInSoTolerant
1006 // Before we call managed code, we probe inside ReverseEnterRuntime for BACKOUT_CODE_STACK_LIMIT pages
1007 // If we hit hard so here, we are still in our stub
1008 (!CLRTaskHosted() || (UINT_PTR)pThread->m_pFrame - pThread->GetLastAllowableStackAddress() >=
1009 ADJUST_PROBE(BACKOUT_CODE_STACK_LIMIT) * OS_PAGE_SIZE)
1012 // Managed exception handler detects SO, but the thread is in preemptive GC mode,
1013 // and the IP is outside CLR. This means we are inside a PINVOKE call.
1014 fInSoTolerant = FALSE;
1018 case SOD_UnmanagedFrameHandler:
1021 case SOD_SOIntolerantTransitor:
1022 fInSoTolerant = FALSE;
1025 case SOD_SOTolerantTransitor:
1028 // If SO happens outside of CLR, and it is not detected by managed frame handler,
1030 fInSoTolerant = FALSE;
1035 _ASSERTE(!"should not get here");
1038 if (fInDefaultDomain)
1040 // StackOverflow in default domain is fatal
1041 fInSoTolerant = FALSE;
1045 #endif // FEATURE_STACK_PROBE
1047 ProcessSOEventForHost(&exceptionInfo, fInSoTolerant);
1049 #ifdef FEATURE_STACK_PROBE
1050 if (!CLRHosted() || GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) != eRudeUnloadAppDomain)
1052 // For security reason, it is not safe to continue execution if stack overflow happens
1053 // unless a host tells us to do something different.
1054 EEPolicy::HandleFatalStackOverflow(&exceptionInfo);
1060 EEPolicy::HandleFatalStackOverflow(&exceptionInfo);
1062 #ifdef FEATURE_STACK_PROBE
1065 // EnableADUnloadWorker is SO_Intolerant.
1066 // But here we know that if we have only one page, we will only update states of the Domain.
1067 CONTRACT_VIOLATION(SOToleranceViolation);
1069 // Mark the current domain requested for rude unload
1070 if (!fInDefaultDomain)
1072 pCurrentDomain->EnableADUnloadWorker(ADU_Rude, FALSE);
1075 pThread->PrepareThreadForSOWork();
1077 pThread->MarkThreadForAbort(
1078 (Thread::ThreadAbortRequester)(Thread::TAR_Thread|Thread::TAR_StackOverflow),
1081 pThread->SetSOWorkNeeded();
1087 // We provide WatsonLastChance with a SO exception record. The ExceptionAddress is set to 0
1088 // here. This ExceptionPointers struct is handed off to the debugger as is. A copy of this struct
1089 // is made before invoking Watson and the ExceptionAddress is set by inspecting the stack. Note
1090 // that the ExceptionContext member is unused and so it's ok to set it to NULL.
1091 static EXCEPTION_RECORD g_SOExceptionRecord = {
1092 STATUS_STACK_OVERFLOW, // ExceptionCode
1093 0, // ExceptionFlags
1094 NULL, // ExceptionRecord
1095 0, // ExceptionAddress
1096 0, // NumberOfParameters
1097 {} }; // ExceptionInformation
1099 EXCEPTION_POINTERS g_SOExceptionPointers = {&g_SOExceptionRecord, NULL};
1101 #ifdef FEATURE_STACK_PROBE
1102 // This function may be called on a thread before debugger is notified of the thread, like in
1103 // ManagedThreadBase_DispatchMiddle. Currently we can not notify managed debugger, because
1104 // RS requires that notification is sent first.
1105 void EEPolicy::HandleSoftStackOverflow(BOOL fSkipDebugger)
1107 WRAPPER_NO_CONTRACT;
1109 // If we trigger a SO while handling the soft stack overflow,
1110 // we'll rip the process
1111 BEGIN_SO_INTOLERANT_CODE_NOPROBE;
1113 AppDomain *pCurrentDomain = ::GetAppDomain();
1115 if (GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) != eRudeUnloadAppDomain ||
1116 pCurrentDomain == SystemDomain::System()->DefaultDomain())
1118 // We may not be able to build a context on stack
1119 ProcessSOEventForHost(NULL, FALSE);
1122 EEPolicy::HandleFatalStackOverflow(&g_SOExceptionPointers, fSkipDebugger);
1124 //else if (pCurrentDomain == SystemDomain::System()->DefaultDomain())
1126 // We hit soft SO in Default domain, but default domain can not be unloaded.
1127 // Soft SO can happen in default domain, eg. GetResourceString, or EnsureGrantSetSerialized.
1128 // So the caller is going to throw a managed exception.
1129 // RaiseException(EXCEPTION_SOFTSO, 0, 0, NULL);
1133 Thread* pThread = GetThread();
1135 if (pThread && pThread->PreemptiveGCDisabled())
1137 // Mark the current domain requested for rude unload
1139 EEPolicy::PerformADUnloadAction(eRudeUnloadAppDomain, TRUE, TRUE);
1142 // We are leaving VM boundary, either entering managed code, or entering
1143 // non-VM unmanaged code.
1144 // We should not throw internal C++ exception. Instead we throw an exception
1145 // with EXCEPTION_SOFTSO code.
1146 RaiseException(EXCEPTION_SOFTSO, 0, 0, NULL);
1149 END_SO_INTOLERANT_CODE_NOPROBE;
1153 void EEPolicy::HandleStackOverflowAfterCatch()
1164 #ifdef STACK_GUARDS_DEBUG
1165 BaseStackGuard::RestoreCurrentGuard(FALSE);
1167 Thread *pThread = GetThread();
1168 pThread->RestoreGuardPage();
1169 pThread->FinishSOWork();
1174 //---------------------------------------------------------------------------------------
1175 // HandleExitProcess is used to shutdown the runtime, based on policy previously set,
1176 // then to exit the process. Note, however, that the process will not exit if
1177 // sca is SCA_ReturnWhenShutdownComplete. In that case, this method will simply return after
1178 // performing the shutdown actions.
1179 //---------------------------------------------------------------------------------------
1180 void EEPolicy::HandleExitProcess(ShutdownCompleteAction sca)
1182 WRAPPER_NO_CONTRACT;
1184 STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleExitProcess\n");
1186 EPolicyAction action = GetEEPolicy()->GetDefaultAction(OPR_ProcessExit, NULL);
1187 GetEEPolicy()->NotifyHostOnDefaultAction(OPR_ProcessExit,action);
1188 HandleExitProcessHelper(action, 0, sca);
1192 // Log an error to the event log if possible, then throw up a dialog box.
1195 void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo)
1197 STATIC_CONTRACT_NOTHROW;
1198 STATIC_CONTRACT_GC_TRIGGERS;
1199 STATIC_CONTRACT_MODE_ANY;
1201 _ASSERTE(pExceptionInfo != NULL);
1203 if(ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, FailFast))
1205 // Fire an ETW FailFast event
1206 FireEtwFailFast(pszMessage,
1207 (const PVOID)address,
1208 ((pExceptionInfo && pExceptionInfo->ExceptionRecord) ? pExceptionInfo->ExceptionRecord->ExceptionCode : 0),
1210 GetClrInstanceId());
1214 // Write an event log entry. We do allocate some resources here (spread between the stack and maybe the heap for longer
1215 // messages), so it's possible for the event write to fail. If needs be we can use a more elaborate scheme here in the future
1216 // (maybe trying multiple approaches and backing off on failure, falling back on a limited size static buffer as a last
1217 // resort). In all likelihood the Win32 event reporting mechanism requires resources though, so it's not clear how much
1218 // effort we should put into this without knowing the benefit we'd receive.
1221 if (ShouldLogInEventLog())
1223 // If the exit code is COR_E_FAILFAST then the fatal error was raised by managed code and the address argument points to a
1224 // unicode message buffer rather than a faulting EIP.
1225 EventReporter::EventReporterType failureType = EventReporter::ERT_UnmanagedFailFast;
1226 if (exitCode == (UINT)COR_E_FAILFAST)
1227 failureType = EventReporter::ERT_ManagedFailFast;
1228 else if (exitCode == (UINT)COR_E_CODECONTRACTFAILED)
1229 failureType = EventReporter::ERT_CodeContractFailed;
1230 EventReporter reporter(failureType);
1233 if ((exitCode == (UINT)COR_E_FAILFAST) || (exitCode == (UINT)COR_E_CODECONTRACTFAILED) || (exitCode == (UINT)CLR_E_GC_OOM))
1237 reporter.AddDescription((WCHAR*)pszMessage);
1240 if (exitCode != (UINT)CLR_E_GC_OOM)
1241 LogCallstackForEventReporter(reporter);
1245 // Fetch the localized Fatal Execution Engine Error text or fall back on a hardcoded variant if things get dire.
1246 InlineSString<80> ssMessage;
1247 InlineSString<80> ssErrorFormat;
1248 if(!ssErrorFormat.LoadResource(CCompRC::Optional, IDS_ER_UNMANAGEDFAILFASTMSG ))
1249 ssErrorFormat.Set(W("at IP %1 (%2) with exit code %3."));
1250 SmallStackSString addressString;
1251 addressString.Printf(W("%p"), pExceptionInfo? (UINT_PTR)pExceptionInfo->ExceptionRecord->ExceptionAddress : address);
1253 // We should always have the reference to the runtime's instance
1254 _ASSERTE(g_pMSCorEE != NULL);
1256 // Setup the string to contain the runtime's base address. Thus, when customers report FEEE with just
1257 // the event log entry containing this string, we can use the absolute and base addresses to determine
1258 // where the fault happened inside the runtime.
1259 SmallStackSString runtimeBaseAddressString;
1260 runtimeBaseAddressString.Printf(W("%p"), g_pMSCorEE);
1262 SmallStackSString exitCodeString;
1263 exitCodeString.Printf(W("%x"), exitCode);
1265 // Format the string
1266 ssMessage.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)ssErrorFormat, 0, 0, addressString, runtimeBaseAddressString,
1268 reporter.AddDescription(ssMessage);
1277 EX_END_CATCH(SwallowAllExceptions)
1278 #endif // !FEATURE_PAL
1281 // If we're native-only (Win32) debugging this process, we'd love to break now.
1282 // However, we should not do this because a managed debugger attached to a
1283 // SxS runtime also appears to be a native debugger. Unfortunately, the managed
1284 // debugger won't handle any native event from another runtime, which means this
1285 // breakpoint would go unhandled and terminate the process. Instead, we will let
1286 // the process continue so at least the fatal error is logged rather than abrupt
1289 // This behavior can still be overridden if the right config value is set.
1290 if (IsDebuggerPresent())
1292 bool fBreak = (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgOOBinFEEE) != 0);
1301 // We're here logging a fatal error. If the policy is to then do anything other than
1302 // disable the runtime (ie, if the policy is to terminate the runtime), we should give
1303 // Watson an opportunity to capture an error report.
1304 // Presumably, hosts that are sophisticated enough to disable the runtime are also cognizant
1305 // of how they want to handle fatal errors in the runtime, including whether they want
1306 // to capture Watson information (for which they are responsible).
1307 if (GetEEPolicy()->GetActionOnFailureNoHostNotification(FAIL_FatalRuntime) != eDisableRuntime)
1309 #ifdef DEBUGGING_SUPPORTED
1310 //Give a managed debugger a chance if this fatal error is on a managed thread.
1311 Thread *pThread = GetThread();
1317 OBJECTHANDLE ohException = NULL;
1319 if (exitCode == (UINT)COR_E_STACKOVERFLOW)
1321 // If we're going down because of stack overflow, go ahead and use the preallocated SO exception.
1322 ohException = CLRException::GetPreallocatedStackOverflowExceptionHandle();
1326 // Though we would like to remove the usage of ExecutionEngineException in any manner,
1327 // we cannot. Its okay to use it in the case below since the process is terminating
1328 // and this will serve as an exception object for debugger.
1329 ohException = CLRException::GetPreallocatedExecutionEngineExceptionHandle();
1332 // Preallocated exception handles can be null if FailFast is invoked before LoadBaseSystemClasses
1333 // (in SystemDomain::Init) finished. See Dev10 Bug 677432 for the detail.
1334 if (ohException != NULL)
1336 // for fail-fast, if there's a LTO available then use that as the inner exception object
1337 // for the FEEE we'll be reporting. this can help the Watson back-end to generate better
1338 // buckets for apps that call Environment.FailFast() and supply an exception object.
1339 OBJECTREF lto = pThread->LastThrownObject();
1341 if (exitCode == static_cast<UINT>(COR_E_FAILFAST) && lto != NULL)
1343 EXCEPTIONREF curEx = (EXCEPTIONREF)ObjectFromHandle(ohException);
1344 curEx->SetInnerException(lto);
1346 pThread->SetLastThrownObject(ObjectFromHandle(ohException), TRUE);
1349 // If a managed debugger is already attached, and if that debugger is thinking it might be inclined to
1350 // try to intercept this excepiton, then tell it that's not possible.
1351 if (pThread->IsExceptionInProgress())
1353 pThread->GetExceptionState()->GetFlags()->SetDebuggerInterceptNotPossible();
1357 if (EXCEPTION_CONTINUE_EXECUTION == WatsonLastChance(pThread, pExceptionInfo, TypeOfReportedError::FatalError))
1359 LOG((LF_EH, LL_INFO100, "EEPolicy::LogFatalError: debugger ==> EXCEPTION_CONTINUE_EXECUTION\n"));
1360 _ASSERTE(!"Debugger should not have returned ContinueExecution");
1362 #endif // DEBUGGING_SUPPORTED
1366 void DisplayStackOverflowException()
1368 LIMITED_METHOD_CONTRACT;
1369 PrintToStdErrA("\n");
1371 PrintToStdErrA("Process is terminating due to StackOverflowException.\n");
1374 void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pExceptionInfo, BOOL fSkipDebugger)
1376 // This is fatal error. We do not care about SO mode any more.
1377 // All of the code from here on out is robust to any failures in any API's that are called.
1378 CONTRACT_VIOLATION(GCViolation | ModeViolation | SOToleranceViolation | FaultNotFatal | TakesLockViolation);
1380 WRAPPER_NO_CONTRACT;
1382 STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleFatalStackOverflow\n");
1384 DisplayStackOverflowException();
1386 if(ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, FailFast))
1388 // Fire an ETW FailFast event
1389 FireEtwFailFast(W("StackOverflowException"),
1390 (const PVOID)((pExceptionInfo && pExceptionInfo->ContextRecord) ? GetIP(pExceptionInfo->ContextRecord) : 0),
1391 ((pExceptionInfo && pExceptionInfo->ExceptionRecord) ? pExceptionInfo->ExceptionRecord->ExceptionCode : 0),
1392 COR_E_STACKOVERFLOW,
1393 GetClrInstanceId());
1398 Thread *pThread = GetThread();
1399 BOOL fTreatAsNativeUnhandledException = FALSE;
1403 // If we had a SO before preallocated exception objects are initialized, we will AV here. This can happen
1404 // during the initialization of SystemDomain during EEStartup. Thus, setup the SO throwable only if its not
1407 // When WatsonLastChance (WLC) is invoked below, it treats this case as UnhandledException. If there is no
1408 // managed exception object available, we should treat this case as NativeUnhandledException. This aligns
1409 // well with the fact that there cannot be a managed debugger attached at this point that will require
1410 // LastChanceManagedException notification to be delivered. Also, this is the same as how
1411 // we treat an unhandled exception as NativeUnhandled when throwable is not available.
1412 OBJECTHANDLE ohSO = CLRException::GetPreallocatedStackOverflowExceptionHandle();
1415 pThread->SafeSetThrowables(ObjectFromHandle(ohSO)
1416 DEBUG_ARG(ThreadExceptionState::STEC_CurrentTrackerEqualNullOkHackForFatalStackOverflow),
1421 // We dont have a throwable - treat this as native unhandled exception
1422 fTreatAsNativeUnhandledException = TRUE;
1425 FrameWithCookie<FaultingExceptionFrame> fef;
1426 #if defined(WIN64EXCEPTIONS)
1427 *((&fef)->GetGSCookiePtr()) = GetProcessGSCookie();
1428 #endif // WIN64EXCEPTIONS
1429 if (pExceptionInfo && pExceptionInfo->ContextRecord)
1432 fef.InitAndLink(pExceptionInfo->ContextRecord);
1436 if (RunningOnWin7() && IsWatsonEnabled() && (g_pDebugInterface != NULL))
1438 _ASSERTE(pExceptionInfo != NULL);
1440 ResetWatsonBucketsParams param;
1441 param.m_pThread = pThread;
1442 param.pExceptionRecord = pExceptionInfo->ExceptionRecord;
1443 g_pDebugInterface->RequestFavor(ResetWatsonBucketsFavorWorker, reinterpret_cast<void *>(¶m));
1445 #endif // !FEATURE_PAL
1447 WatsonLastChance(pThread, pExceptionInfo,
1448 (fTreatAsNativeUnhandledException == FALSE)? TypeOfReportedError::UnhandledException: TypeOfReportedError::NativeThreadUnhandledException);
1451 TerminateProcess(GetCurrentProcess(), COR_E_STACKOVERFLOW);
1455 void DECLSPEC_NORETURN EEPolicy::HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage /* = NULL */, PEXCEPTION_POINTERS pExceptionInfo /* = NULL */)
1457 WRAPPER_NO_CONTRACT;
1459 // All of the code from here on out is robust to any failures in any API's that are called.
1462 EXCEPTION_RECORD exceptionRecord;
1463 EXCEPTION_POINTERS exceptionPointers;
1466 if (pExceptionInfo == NULL)
1468 ZeroMemory(&exceptionPointers, sizeof(exceptionPointers));
1469 ZeroMemory(&exceptionRecord, sizeof(exceptionRecord));
1470 ZeroMemory(&context, sizeof(context));
1472 context.ContextFlags = CONTEXT_CONTROL;
1473 ClrCaptureContext(&context);
1475 exceptionRecord.ExceptionCode = exitCode;
1476 exceptionRecord.ExceptionAddress = reinterpret_cast< PVOID >(address);
1478 exceptionPointers.ExceptionRecord = &exceptionRecord;
1479 exceptionPointers.ContextRecord = &context;
1480 pExceptionInfo = &exceptionPointers;
1483 // All of the code from here on out is allowed to trigger a GC, even if we're in a no-trigger region. We're
1484 // ripping the process down due to a fatal error... our invariants are already gone.
1486 // This is fatal error. We do not care about SO mode any more.
1487 // All of the code from here on out is robust to any failures in any API's that are called.
1488 CONTRACT_VIOLATION(GCViolation | ModeViolation | SOToleranceViolation | FaultNotFatal | TakesLockViolation);
1490 // ThreadStore lock needs to be released before continuing with the FatalError handling should
1491 // because debugger is going to take CrstDebuggerMutex, whose lock level is higher than that of
1492 // CrstThreadStore. It should be safe to release the lock since execution will not be resumed
1493 // after fatal errors.
1494 if (ThreadStore::HoldingThreadStore(GetThread()))
1496 ThreadSuspend::UnlockThreadStore();
1499 g_fFastExitProcess = 2;
1501 STRESS_LOG0(LF_CORDB,LL_INFO100, "D::HFE: About to call LogFatalError\n");
1502 switch (GetEEPolicy()->GetActionOnFailure(FAIL_FatalRuntime))
1504 case eRudeExitProcess:
1505 LogFatalError(exitCode, address, pszMessage, pExceptionInfo);
1506 SafeExitProcess(exitCode, TRUE);
1508 case eDisableRuntime:
1509 LogFatalError(exitCode, address, pszMessage, pExceptionInfo);
1510 DisableRuntime(SCA_ExitProcessWhenShutdownComplete);
1513 _ASSERTE(!"Invalid action for FAIL_FatalRuntime");
1521 void EEPolicy::HandleExitProcessFromEscalation(EPolicyAction action, UINT exitCode)
1523 WRAPPER_NO_CONTRACT;
1524 CONTRACT_VIOLATION(GCViolation);
1526 _ASSERTE (action >= eExitProcess);
1527 // If policy for ExitProcess is not default action, i.e. ExitProcess, we will use it.
1528 // Otherwise overwrite it with passing arg action;
1529 EPolicyAction todo = GetEEPolicy()->GetDefaultAction(OPR_ProcessExit, NULL);
1530 if (todo == eExitProcess)
1534 GetEEPolicy()->NotifyHostOnDefaultAction(OPR_ProcessExit,todo);
1536 HandleExitProcessHelper(todo, exitCode, SCA_ExitProcessWhenShutdownComplete);
1539 void EEPolicy::HandleCodeContractFailure(LPCWSTR pMessage, LPCWSTR pCondition, LPCWSTR pInnerExceptionAsString)
1541 WRAPPER_NO_CONTRACT;
1543 EEPolicy* pPolicy = GetEEPolicy();
1544 // GetActionOnFailure will notify the host for us.
1545 EPolicyAction action = pPolicy->GetActionOnFailure(FAIL_CodeContract);
1546 Thread* pThread = GetThread();
1547 AppDomain* pCurrentDomain = ::GetAppDomain();
1550 case eThrowException:
1551 // Let managed code throw a ContractException (it's easier to pass the right parameters to the constructor).
1554 pThread->UserAbort(Thread::TAR_Thread, TA_Safe, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
1556 case eRudeAbortThread:
1557 pThread->UserAbort(Thread::TAR_Thread, TA_Rude, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
1559 case eUnloadAppDomain:
1560 // Register an appdomain unload, which starts on a separate thread.
1561 IfFailThrow(AppDomain::UnloadById(pCurrentDomain->GetId(), FALSE));
1562 // Don't continue execution on this thread.
1563 pThread->UserAbort(Thread::TAR_Thread, TA_Safe, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
1565 case eRudeUnloadAppDomain:
1566 pCurrentDomain->SetRudeUnload();
1567 // Register an appdomain unload, which starts on a separate thread.
1568 IfFailThrow(AppDomain::UnloadById(pCurrentDomain->GetId(), FALSE));
1569 // Don't continue execution on this thread.
1570 pThread->UserAbort(Thread::TAR_Thread, TA_Rude, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
1573 case eExitProcess: // Merged w/ default case
1575 _ASSERTE(action == eExitProcess);
1576 // Since we have no exception object, make sure
1577 // UE tracker is clean so that RetrieveManagedBucketParameters
1578 // does not take any bucket details.
1580 pThread->GetExceptionState()->GetUEWatsonBucketTracker()->ClearWatsonBucketDetails();
1581 #endif // !FEATURE_PAL
1582 pPolicy->HandleFatalError(COR_E_CODECONTRACTFAILED, NULL, pMessage);