Fixing the StackOverflowException error message. (#4786)
[platform/upstream/coreclr.git] / src / vm / eepolicy.cpp
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.
4 //
5
6 //
7 // ---------------------------------------------------------------------------
8 // EEPolicy.cpp
9 // ---------------------------------------------------------------------------
10
11
12 #include "common.h"
13 #include "eepolicy.h"
14 #include "corhost.h"
15 #include "dbginterface.h"
16 #include "eemessagebox.h"
17
18 #include "eventreporter.h"
19 #include "finalizerthread.h"
20 #include "threadsuspend.h"
21
22 #ifndef FEATURE_PAL
23 #include "dwreport.h"
24 #endif // !FEATURE_PAL
25
26 #include "eventtrace.h"
27 #undef ExitProcess
28
29 BYTE g_EEPolicyInstance[sizeof(EEPolicy)];
30
31 void InitEEPolicy()
32 {
33     WRAPPER_NO_CONTRACT;
34     new (g_EEPolicyInstance) EEPolicy();
35 }
36
37 EEPolicy::EEPolicy ()
38 {
39     CONTRACTL
40     {
41         GC_NOTRIGGER;
42         NOTHROW;
43     }
44     CONTRACTL_END;
45     
46     int n;
47     for (n = 0; n < MaxClrOperation; n++) {
48         m_Timeout[n] = INFINITE;
49         m_ActionOnTimeout[n] = eNoAction;
50         m_DefaultAction[n] = eNoAction;
51     }
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;
57
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;
65
66     for (n = 0; n < MaxClrFailure; n++) {
67         m_ActionOnFailure[n] = eNoAction;
68     }
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;
82 }
83
84 BOOL EEPolicy::IsValidActionForOperation(EClrOperation operation, EPolicyAction action)
85 {
86     CONTRACTL
87     {
88         GC_NOTRIGGER;
89         NOTHROW;
90     }
91     CONTRACTL_END;
92     
93     switch (operation) {
94     case OPR_ThreadAbort:
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);
114     default:
115         _ASSERT (!"Do not know valid action for this operation");
116         break;
117     }
118     return FALSE;
119 }
120
121 BOOL EEPolicy::IsValidActionForTimeout(EClrOperation operation, EPolicyAction action)
122 {
123     CONTRACTL
124     {
125         GC_NOTRIGGER;
126         NOTHROW;
127     }
128     CONTRACTL_END;
129     
130     switch (operation) {
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);
151     default:
152         _ASSERT (!"Do not know valid action for this operation");
153         break;
154     }
155     return FALSE;
156 }
157
158 BOOL EEPolicy::IsValidActionForFailure(EClrFailure failure, EPolicyAction action)
159 {
160     CONTRACTL
161     {
162         GC_NOTRIGGER;
163         NOTHROW;
164     }
165     CONTRACTL_END;
166     
167     switch (failure) {
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:
183         // 
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.
191         //
192         // That said, currently, Desktop CLR does not support
193         // FAIL_AccessViolation. Thus, any calls which use
194         // this failure are not allowed.
195         return FALSE;
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;
203     default:
204         _ASSERTE (!"Do not know valid action for this failure");
205         break;
206     }
207
208     return FALSE;
209 }
210
211 HRESULT EEPolicy::SetTimeout(EClrOperation operation, DWORD timeout)
212 {
213     CONTRACTL 
214     {
215         MODE_ANY;
216         GC_NOTRIGGER;
217         NOTHROW;
218     }
219     CONTRACTL_END;
220
221     if (static_cast<UINT>(operation) < MaxClrOperation)
222     {
223     m_Timeout[operation] = timeout;
224     if (operation == OPR_FinalizerRun &&
225         g_fEEStarted)
226     {
227         FastInterlockOr((DWORD*)&g_FinalizerWaiterStatus, FWS_WaitInterrupt);
228         FinalizerThread::SignalFinalizationDone(FALSE);
229     }
230     return S_OK;
231 }
232     else
233     {
234         return E_INVALIDARG;
235     }
236 }
237
238 HRESULT EEPolicy::SetActionOnTimeout(EClrOperation operation, EPolicyAction action)
239 {
240     CONTRACTL
241     {
242         GC_NOTRIGGER;
243         NOTHROW;
244     }
245     CONTRACTL_END;
246     
247     if (static_cast<UINT>(operation) < MaxClrOperation &&
248         IsValidActionForTimeout(operation, action))
249     {
250         m_ActionOnTimeout[operation] = action;
251         return S_OK;
252     }
253     else
254     {
255         return E_INVALIDARG;
256     }
257 }
258
259 EPolicyAction EEPolicy::GetFinalAction(EPolicyAction action, Thread *pThread)
260 {
261     LIMITED_METHOD_CONTRACT;
262     _ASSERTE(static_cast<UINT>(action) < MaxPolicyAction);
263
264     if (action < eAbortThread || action > eFastExitProcess)
265     {
266         return action;
267     }
268
269     while(TRUE)
270     {
271         // Look at default action.  If the default action is more severe,
272         // use the default action instead.
273         EPolicyAction defaultAction = action;
274         switch (action)
275         {
276             case eAbortThread:
277             defaultAction = m_DefaultAction[OPR_ThreadAbort];
278                 break;
279             case eRudeAbortThread:
280                 if (pThread && !pThread->HasLockInCurrentDomain())
281                 {
282                 defaultAction = m_DefaultAction[OPR_ThreadRudeAbortInNonCriticalRegion];
283                 }
284                 else
285                 {
286                 defaultAction = m_DefaultAction[OPR_ThreadRudeAbortInCriticalRegion];
287                 }
288                 break;
289             case eUnloadAppDomain:
290             defaultAction = m_DefaultAction[OPR_AppDomainUnload];
291                 break;
292             case eRudeUnloadAppDomain:
293             defaultAction = m_DefaultAction[OPR_AppDomainRudeUnload];
294                 break;
295             case eExitProcess:
296             case eFastExitProcess:
297             defaultAction = m_DefaultAction[OPR_ProcessExit];
298             if (defaultAction < action)
299                 {
300                 defaultAction = action;
301                 }
302                 break;
303             default:
304                 break;
305             }
306         _ASSERTE(static_cast<UINT>(defaultAction) < MaxPolicyAction);
307
308         if (defaultAction == action)
309             {
310             return action;
311             }
312
313         _ASSERTE(defaultAction > action);
314         action = defaultAction;
315     }
316 }
317
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)
322 {
323     CONTRACTL
324     {
325         GC_NOTRIGGER;
326         NOTHROW;
327     }
328     CONTRACTL_END;
329     
330     if (static_cast<UINT>(operation) < MaxClrOperation &&
331         IsValidActionForTimeout(operation, action))
332     {
333         m_ActionOnTimeout[operation] = action;
334         m_Timeout[operation] = timeout;
335         if (operation == OPR_FinalizerRun &&
336             g_fEEStarted)
337         {
338             FastInterlockOr((DWORD*)&g_FinalizerWaiterStatus, FWS_WaitInterrupt);
339             FinalizerThread::SignalFinalizationDone(FALSE);
340         }
341         return S_OK;
342     }
343     else
344     {
345         return E_INVALIDARG;
346     }
347 }
348
349 HRESULT EEPolicy::SetDefaultAction(EClrOperation operation, EPolicyAction action)
350 {
351     CONTRACTL
352     {
353         GC_NOTRIGGER;
354         NOTHROW;
355     }
356     CONTRACTL_END;
357     
358     if (static_cast<UINT>(operation) < MaxClrOperation &&
359         IsValidActionForOperation(operation, action))
360     {
361         m_DefaultAction[operation] = action;
362         return S_OK;
363     }
364     else
365     {
366         return E_INVALIDARG;
367     }
368 }
369
370 HRESULT EEPolicy::SetActionOnFailure(EClrFailure failure, EPolicyAction action)
371 {
372     CONTRACTL
373     {
374         GC_NOTRIGGER;
375         NOTHROW;
376     }
377     CONTRACTL_END;
378
379     if (static_cast<UINT>(failure) < MaxClrFailure &&
380         IsValidActionForFailure(failure, action))
381     {
382         m_ActionOnFailure[failure] = action;
383         return S_OK;
384     }
385     else
386     {
387         return E_INVALIDARG;
388     }
389 }
390
391 EPolicyAction EEPolicy::GetActionOnFailureNoHostNotification(EClrFailure failure)
392 {
393     CONTRACTL 
394     {
395         SO_TOLERANT;
396         MODE_ANY;
397         GC_NOTRIGGER;
398         NOTHROW;
399     }CONTRACTL_END;
400
401     _ASSERTE (failure < MaxClrFailure);
402     if (failure == FAIL_StackOverflow)
403     {
404         return m_ActionOnFailure[failure];
405     }
406
407     return GetFinalAction(m_ActionOnFailure[failure], GetThread());
408 }
409
410 EPolicyAction EEPolicy::GetActionOnFailure(EClrFailure failure)
411 {
412     CONTRACTL 
413     {
414         SO_TOLERANT;
415         MODE_ANY;
416         GC_NOTRIGGER;
417         NOTHROW;
418     }CONTRACTL_END;
419
420     _ASSERTE(static_cast<UINT>(failure) < MaxClrFailure);
421     if (failure == FAIL_StackOverflow)
422     {
423         return m_ActionOnFailure[failure];
424     }
425
426     EPolicyAction finalAction = GetActionOnFailureNoHostNotification(failure);
427 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
428     IHostPolicyManager *pHostPolicyManager = CorHost2::GetHostPolicyManager();
429     if (pHostPolicyManager)
430     {
431 #ifdef _DEBUG
432         Thread* pThread = GetThread();
433         if (pThread)
434         {
435             pThread->AddFiberInfo(Thread::ThreadTrackInfo_Escalation);
436         }
437 #endif
438         BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
439         pHostPolicyManager->OnFailure(failure, finalAction);
440         END_SO_TOLERANT_CODE_CALLING_HOST;
441     }
442 #endif // FEATURE_INCLUDE_ALL_INTERFACES
443     return finalAction;
444 }
445
446
447 void EEPolicy::NotifyHostOnTimeout(EClrOperation operation, EPolicyAction action)
448 {
449     CONTRACTL
450     {
451         THROWS;
452         GC_NOTRIGGER;
453         MODE_ANY;
454         SO_TOLERANT;
455     }
456     CONTRACTL_END;
457
458 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
459     IHostPolicyManager *pHostPolicyManager = CorHost2::GetHostPolicyManager();
460     if (pHostPolicyManager)
461     {
462 #ifdef _DEBUG
463         Thread* pThread = GetThread();
464         if (pThread)
465         {
466             pThread->AddFiberInfo(Thread::ThreadTrackInfo_Escalation);
467         }
468 #endif
469         BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
470         pHostPolicyManager->OnTimeout(operation, action);
471         END_SO_TOLERANT_CODE_CALLING_HOST;
472     }
473 #endif // FEATURE_INCLUDE_ALL_INTERFACES
474 }
475
476
477 void EEPolicy::NotifyHostOnDefaultAction(EClrOperation operation, EPolicyAction action)
478 {
479     CONTRACTL
480     {
481         NOTHROW;
482         GC_NOTRIGGER;
483         MODE_ANY;
484         SO_TOLERANT;
485     }
486     CONTRACTL_END;
487
488 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
489     IHostPolicyManager *pHostPolicyManager = CorHost2::GetHostPolicyManager();
490     if (pHostPolicyManager)
491     {
492 #ifdef _DEBUG
493         Thread* pThread = GetThread();
494         if (pThread)
495         {
496             pThread->AddFiberInfo(Thread::ThreadTrackInfo_Escalation);
497         }
498 #endif
499         BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
500         pHostPolicyManager->OnDefaultAction(operation, action);
501         END_SO_TOLERANT_CODE_CALLING_HOST;
502     }
503 #endif // FEATURE_INCLUDE_ALL_INTERFACES
504 }
505
506 void SafeExitProcess(UINT exitCode, BOOL fAbort = FALSE, ShutdownCompleteAction sca = SCA_ExitProcessWhenShutdownComplete)
507 {
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);
511     CONTRACTL
512     {
513         DISABLED(GC_TRIGGERS);
514         NOTHROW;
515     }
516     CONTRACTL_END;
517
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();
522     
523     FastInterlockExchange((LONG*)&g_fForbidEnterEE, TRUE);
524     
525     ProcessEventForHost(Event_ClrDisabled, NULL);
526     
527     // Note that for free and retail builds StressLog must also be enabled
528     if (g_pConfig && g_pConfig->StressLog())
529     {
530         if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_BreakOnBadExit))
531         {
532             // Workaround for aspnet
533             PathString  wszFilename;
534             bool bShouldAssert = true;
535             if (WszGetModuleFileName(NULL, wszFilename))
536             {
537                 wszFilename.LowerCase();
538                 
539                 if (wcsstr(wszFilename, W("aspnet_compiler"))) 
540                 {
541                     bShouldAssert = false;
542                 }                   
543             }
544             
545             unsigned goodExit = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_SuccessExit);
546             if (bShouldAssert && exitCode != goodExit)
547             {
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"));
552             }
553         }
554     }
555     
556     // If we call ExitProcess, other threads will be torn down 
557     // so we don't get to debug their state.  Stop this!
558 #ifdef _DEBUG
559     if (_DbgBreakCount)
560         _ASSERTE(!"In SafeExitProcess: An assert was hit on some other thread");
561 #endif
562
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"));
569
570     if (sca == SCA_ExitProcessWhenShutdownComplete)
571     {
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);
575
576 #ifdef FEATURE_PAL
577         if (fAbort)
578         {
579             TerminateProcess(GetCurrentProcess(), exitCode);
580         }
581 #endif
582
583         EEPolicy::ExitProcessViaShim(exitCode);
584     }
585 }
586
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. 
591 //
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.
595
596 //static 
597 void EEPolicy::ExitProcessViaShim(UINT exitCode)
598 {
599     LIMITED_METHOD_CONTRACT;
600
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)
606     {
607         ReleaseHolder<ICLRRuntimeHostInternal> pRuntimeHostInternal;
608
609         HRESULT hr = g_pCLRRuntime->GetInterface(CLSID_CLRRuntimeHostInternal,
610             IID_ICLRRuntimeHostInternal,
611             &pRuntimeHostInternal);
612
613         if (SUCCEEDED(hr))
614         {
615             pRuntimeHostInternal->ShutdownAllRuntimesThenExit(exitCode);
616             LOG((LF_EH, LL_INFO10, "ExitProcessViaShim: shim returned... exiting now.\n"));
617         }
618     }
619 #endif // !FEATURE_CORECLR
620
621     ExitProcess(exitCode);
622 }
623
624
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)
631 {
632     CONTRACTL
633     {
634         DISABLED(GC_TRIGGERS);
635         NOTHROW;
636     }
637     CONTRACTL_END;
638
639     FastInterlockExchange((LONG*)&g_fForbidEnterEE, TRUE);
640     
641     if (!g_fSuspendOnShutdown)
642     {
643         if (!IsGCThread())
644         {
645             if (ThreadStore::HoldingThreadStore(GetThread()))
646             {
647                 ThreadSuspend::UnlockThreadStore();
648             }
649             ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_SHUTDOWN);
650         }
651
652         if (!g_fSuspendOnShutdown)
653         {
654             ThreadStore::TrapReturningThreads(TRUE);
655             g_fSuspendOnShutdown = TRUE;
656             ClrFlsSetThreadType(ThreadType_Shutdown);
657         }
658
659         // Don't restart runtime.  CLR is disabled.
660     }
661
662     GCX_PREEMP_NO_DTOR();
663     
664     ProcessEventForHost(Event_ClrDisabled, NULL);
665     ClrFlsClearThreadType(ThreadType_Shutdown);
666
667     if (g_pDebugInterface != NULL)
668     {
669         g_pDebugInterface->DisableDebugger();
670     }
671
672     if (sca == SCA_ExitProcessWhenShutdownComplete)
673     {
674         __SwitchToThread(INFINITE, CALLER_LIMITS_SPINNING);
675         _ASSERTE (!"Should not reach here");
676         SafeExitProcess(0);
677     }
678 }
679
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 //---------------------------------------------------------------------------------------
686
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;
691
692 extern void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading);
693
694 static void HandleExitProcessHelper(EPolicyAction action, UINT exitCode, ShutdownCompleteAction sca)
695 {
696     WRAPPER_NO_CONTRACT;
697     
698     switch (action) {
699     case eFastExitProcess:
700         g_fFastExitProcess = 1;
701     case eExitProcess:
702         if (g_fEEStarted)
703         {
704             EEShutDown(FALSE);
705         }
706         if (exitCode == 0)
707         {
708             exitCode = GetLatchedExitCode();
709         }
710         SafeExitProcess(exitCode, FALSE, sca);
711         break;
712     case eRudeExitProcess:
713         g_fFastExitProcess = 2;
714         SafeExitProcess(exitCode, TRUE, sca);
715         break;
716     case eDisableRuntime:
717         DisableRuntime(sca);
718         break;
719     default:
720         _ASSERTE (!"Invalid policy");
721         break;
722     }
723 }
724
725
726 EPolicyAction EEPolicy::DetermineResourceConstraintAction(Thread *pThread)
727 {
728     CONTRACTL
729     {
730         NOTHROW;
731         GC_NOTRIGGER;
732         SO_TOLERANT;
733         MODE_ANY;
734     }
735     CONTRACTL_END;
736
737     EPolicyAction action;
738     if (pThread->HasLockInCurrentDomain()) {
739         action = GetEEPolicy()->GetActionOnFailure(FAIL_CriticalResource);
740     }
741     else
742         action = GetEEPolicy()->GetActionOnFailure(FAIL_NonCriticalResource);
743
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))
748     {
749         action = eThrowException;
750     }
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) 
754     {
755         action = eThrowException;
756     }
757     return action;
758 }
759
760
761 void EEPolicy::PerformADUnloadAction(EPolicyAction action, BOOL haveStack, BOOL forStackOverflow)
762 {
763     STATIC_CONTRACT_THROWS;
764     STATIC_CONTRACT_GC_TRIGGERS;
765     STATIC_CONTRACT_MODE_COOPERATIVE;
766     
767     STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::PerformADUnloadAction\n");       
768
769     Thread *pThread = GetThread();
770
771     AppDomain *pDomain = GetAppDomain();
772
773     if (!IsFinalizerThread())
774     {
775         int count = 0;
776         Frame *pFrame = pThread->GetFirstTransitionInto(GetAppDomain(), &count);
777         {
778             pThread->SetUnloadBoundaryFrame(pFrame);
779         }
780     }
781
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. 
785     if (haveStack)
786     {
787         pThread->SetAbortRequest(action==eUnloadAppDomain? EEPolicy::TA_V1Compatible : EEPolicy::TA_Rude);
788         if (forStackOverflow)
789         {
790             OBJECTREF exceptObj = CLRException::GetPreallocatedRudeThreadAbortException();
791             pThread->SetAbortInitiated();
792             RaiseTheExceptionInternalOnly(exceptObj, FALSE, TRUE);
793         }
794
795         OBJECTREF exceptObj = CLRException::GetPreallocatedThreadAbortException();
796         pThread->SetAbortInitiated();
797         RaiseTheExceptionInternalOnly(exceptObj, FALSE, FALSE);
798     }
799 }
800
801 void EEPolicy::PerformResourceConstraintAction(Thread *pThread, EPolicyAction action, UINT exitCode, BOOL haveStack)
802     {
803     WRAPPER_NO_CONTRACT;
804
805     _ASSERTE(GetAppDomain() != NULL);
806
807     switch (action) {
808     case eThrowException:
809         // Caller is going to rethrow.
810         return;
811         break;
812     case eAbortThread:
813         pThread->UserAbort(Thread::TAR_Thread, TA_Safe, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
814         break;
815     case eRudeAbortThread:
816         pThread->UserAbort(Thread::TAR_Thread, TA_Rude, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
817         break;
818     case eUnloadAppDomain:
819     case eRudeUnloadAppDomain:
820             {
821                 GCX_ASSERT_COOP();
822         PerformADUnloadAction(action,haveStack);
823             }
824         break;
825     case eExitProcess:
826     case eFastExitProcess:
827     case eRudeExitProcess:
828     case eDisableRuntime:
829         HandleExitProcessFromEscalation(action, exitCode);
830         break;
831     default:
832         _ASSERTE (!"Invalid policy");
833         break;
834     }
835 }
836
837 void EEPolicy::HandleOutOfMemory()
838 {
839     WRAPPER_NO_CONTRACT;
840
841     _ASSERTE (g_pOutOfMemoryExceptionClass);
842
843     Thread *pThread = GetThread();
844     _ASSERTE (pThread);
845
846     EPolicyAction action = DetermineResourceConstraintAction(pThread);
847     
848     // Check if we are executing in the context of a Constrained Execution Region.
849     if (action != eThrowException && Thread::IsExecutingWithinCer())
850     {
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.
855         return;
856     }
857
858     PerformResourceConstraintAction(pThread, action, HOST_E_EXITPROCESS_OUTOFMEMORY, TRUE);
859 }
860
861 #ifdef FEATURE_STACK_PROBE
862 //---------------------------------------------------------------------------------------
863 //
864 // IsSOTolerant - Is the current thread in SO Tolerant region?
865 //
866 // Arguments:
867 //    pLimitFrame: the limit of search for frames
868 //
869 // Return Value:
870 //    TRUE if in SO tolerant region.
871 //    FALSE if in SO intolerant region.
872 // 
873 // Note:
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.
876 //
877 BOOL Thread::IsSOTolerant(void * pLimitFrame)
878 {
879     LIMITED_METHOD_CONTRACT;
880
881     Frame *pFrame = GetFrame();
882     void* pSOIntolerantMarker = ClrFlsGetValue(TlsIdx_SOIntolerantTransitionHandler);
883     if (pSOIntolerantMarker == FRAME_TOP)
884     {
885         // We have not set a marker for intolerant transition yet.
886         return TRUE;
887     }
888     while (pFrame != FRAME_TOP && pFrame < pLimitFrame)
889     {
890         Frame::ETransitionType type = pFrame->GetTransitionType();
891         if (pFrame > pSOIntolerantMarker)
892         {
893             return FALSE;
894         }
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)
899         {
900             return TRUE;
901         }
902         pFrame = pFrame->Next();
903     }
904
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.
908         return FALSE;
909     else
910         return TRUE;
911 }
912
913 #endif
914
915 //---------------------------------------------------------------------------------------
916 //
917 // EEPolicy::HandleStackOverflow - Handle stack overflow according to policy
918 //
919 // Arguments:
920 //    detector: 
921 //    pLimitFrame: the limit of search for frames in order to decide if in SO tolerant
922 //
923 // Return Value:
924 //    None.
925 // 
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.
938 //
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)
942 {
943     WRAPPER_NO_CONTRACT;
944     
945     STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleStackOverflow\n");
946
947     Thread *pThread = GetThread();
948
949     if (pThread == NULL)
950     {
951         //_ASSERTE (detector != SOD_ManagedFrameHandler);
952         // ProcessSOEventForHost(NULL, FALSE);
953
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);
957         return;
958     }
959
960 #ifdef FEATURE_STACK_PROBE
961
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)
968     {
969         return;
970     }
971 #endif
972
973 #ifdef FEATURE_STACK_PROBE
974     BOOL fInSoTolerant = pThread->IsSOTolerant(pLimitFrame);
975 #else
976     BOOL fInSoTolerant = false;
977 #endif
978
979     EXCEPTION_POINTERS exceptionInfo;
980     GetCurrentExceptionPointers(&exceptionInfo);
981
982     _ASSERTE(exceptionInfo.ExceptionRecord);
983
984 #ifdef FEATURE_STACK_PROBE
985     DWORD exceptionCode = exceptionInfo.ExceptionRecord->ExceptionCode;
986
987     AppDomain *pCurrentDomain = ::GetAppDomain();
988     BOOL fInDefaultDomain = (pCurrentDomain == SystemDomain::System()->DefaultDomain());
989     BOOL fInCLR = IsIPInModule(g_pMSCorEE, (PCODE)GetIP(exceptionInfo.ContextRecord));
990
991     if (exceptionCode == EXCEPTION_SOFTSO)
992     {
993         // Our probe detects a thread does not have enough stack.  But we have not trashed the process
994         // state yet.
995         fInSoTolerant = TRUE;
996     }
997     else
998     {
999         _ASSERTE (exceptionCode == STATUS_STACK_OVERFLOW);
1000
1001     switch (detector)
1002     {
1003     case SOD_ManagedFrameHandler:
1004             if (!pThread->PreemptiveGCDisabled() && !fInCLR && fInSoTolerant
1005             &&
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)
1010             )
1011         {
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;
1015         }
1016             break;
1017
1018         case SOD_UnmanagedFrameHandler:
1019         break;
1020
1021     case SOD_SOIntolerantTransitor:
1022             fInSoTolerant = FALSE;
1023         break;
1024
1025     case SOD_SOTolerantTransitor:
1026         if (!fInCLR)
1027         {
1028             // If SO happens outside of CLR, and it is not detected by managed frame handler,
1029             // it is fatal
1030             fInSoTolerant = FALSE;
1031         }
1032         break;
1033
1034     default:
1035         _ASSERTE(!"should not get here");
1036     }
1037
1038         if (fInDefaultDomain)
1039         {
1040             // StackOverflow in default domain is fatal
1041             fInSoTolerant = FALSE;
1042         }
1043     }
1044
1045 #endif // FEATURE_STACK_PROBE
1046
1047     ProcessSOEventForHost(&exceptionInfo, fInSoTolerant);
1048
1049 #ifdef FEATURE_STACK_PROBE
1050     if (!CLRHosted() || GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) != eRudeUnloadAppDomain)
1051     {
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);
1055     }
1056 #endif
1057
1058     if (!fInSoTolerant)
1059     {
1060         EEPolicy::HandleFatalStackOverflow(&exceptionInfo);
1061     }
1062 #ifdef FEATURE_STACK_PROBE
1063     else
1064     {
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);
1068
1069         // Mark the current domain requested for rude unload
1070         if (!fInDefaultDomain)
1071         {
1072         pCurrentDomain->EnableADUnloadWorker(ADU_Rude, FALSE);
1073         }
1074
1075         pThread->PrepareThreadForSOWork();
1076
1077         pThread->MarkThreadForAbort(
1078             (Thread::ThreadAbortRequester)(Thread::TAR_Thread|Thread::TAR_StackOverflow),
1079             EEPolicy::TA_Rude);
1080
1081         pThread->SetSOWorkNeeded();
1082     }
1083 #endif
1084 }
1085
1086
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
1098                
1099 EXCEPTION_POINTERS g_SOExceptionPointers = {&g_SOExceptionRecord, NULL};
1100
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)
1106 {
1107     WRAPPER_NO_CONTRACT;
1108
1109     // If we trigger a SO while handling the soft stack overflow,
1110     // we'll rip the process
1111     BEGIN_SO_INTOLERANT_CODE_NOPROBE;
1112     
1113     AppDomain *pCurrentDomain = ::GetAppDomain();
1114
1115     if (GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) != eRudeUnloadAppDomain ||
1116         pCurrentDomain == SystemDomain::System()->DefaultDomain())
1117     {
1118         // We may not be able to build a context on stack
1119         ProcessSOEventForHost(NULL, FALSE);
1120
1121         
1122         EEPolicy::HandleFatalStackOverflow(&g_SOExceptionPointers, fSkipDebugger);
1123     }
1124     //else if (pCurrentDomain == SystemDomain::System()->DefaultDomain())
1125     //{
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);
1130     //}
1131     else
1132     {
1133         Thread* pThread = GetThread();
1134         
1135         if (pThread && pThread->PreemptiveGCDisabled())
1136         {
1137             // Mark the current domain requested for rude unload
1138             GCX_ASSERT_COOP();
1139             EEPolicy::PerformADUnloadAction(eRudeUnloadAppDomain, TRUE, TRUE);
1140         }
1141
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);
1147     }
1148
1149     END_SO_INTOLERANT_CODE_NOPROBE;
1150     
1151 }
1152
1153 void EEPolicy::HandleStackOverflowAfterCatch()
1154 {
1155     CONTRACTL
1156     {
1157         NOTHROW;
1158         GC_NOTRIGGER;
1159         SO_TOLERANT;
1160         MODE_ANY;
1161     }
1162     CONTRACTL_END;
1163
1164 #ifdef STACK_GUARDS_DEBUG
1165     BaseStackGuard::RestoreCurrentGuard(FALSE);
1166 #endif
1167     Thread *pThread = GetThread();
1168     pThread->RestoreGuardPage();
1169     pThread->FinishSOWork();
1170 }
1171 #endif
1172
1173
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)
1181 {
1182     WRAPPER_NO_CONTRACT;    
1183
1184     STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleExitProcess\n");
1185     
1186     EPolicyAction action = GetEEPolicy()->GetDefaultAction(OPR_ProcessExit, NULL);
1187     GetEEPolicy()->NotifyHostOnDefaultAction(OPR_ProcessExit,action);
1188     HandleExitProcessHelper(action, 0, sca);
1189 }
1190
1191 //
1192 // Log an error to the event log if possible, then throw up a dialog box.
1193 //
1194
1195 void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo)
1196 {
1197     STATIC_CONTRACT_NOTHROW;
1198     STATIC_CONTRACT_GC_TRIGGERS;
1199     STATIC_CONTRACT_MODE_ANY;
1200
1201     _ASSERTE(pExceptionInfo != NULL);
1202
1203     if(ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, FailFast))
1204     {
1205         // Fire an ETW FailFast event
1206         FireEtwFailFast(pszMessage, 
1207                         (const PVOID)address, 
1208                         ((pExceptionInfo && pExceptionInfo->ExceptionRecord) ? pExceptionInfo->ExceptionRecord->ExceptionCode : 0), 
1209                         exitCode, 
1210                         GetClrInstanceId());
1211     }
1212
1213 #ifndef FEATURE_PAL
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.
1219     EX_TRY
1220     {
1221         if (ShouldLogInEventLog())
1222         {
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);
1231
1232
1233             if ((exitCode == (UINT)COR_E_FAILFAST) || (exitCode == (UINT)COR_E_CODECONTRACTFAILED) || (exitCode == (UINT)CLR_E_GC_OOM))
1234             {
1235                 if (pszMessage)
1236                 {
1237                     reporter.AddDescription((WCHAR*)pszMessage);
1238                 }
1239
1240                 if (exitCode != (UINT)CLR_E_GC_OOM)
1241                     LogCallstackForEventReporter(reporter);
1242             }
1243             else
1244             {
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);
1252
1253                 // We should always have the reference to the runtime's instance
1254                 _ASSERTE(g_pMSCorEE != NULL);
1255
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);
1261
1262                 SmallStackSString exitCodeString;
1263                 exitCodeString.Printf(W("%x"), exitCode);
1264
1265                 // Format the string
1266                 ssMessage.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)ssErrorFormat, 0, 0, addressString, runtimeBaseAddressString, 
1267                     exitCodeString);
1268                 reporter.AddDescription(ssMessage);
1269             }
1270
1271             reporter.Report();
1272         }
1273     }
1274     EX_CATCH
1275     {
1276     }
1277     EX_END_CATCH(SwallowAllExceptions)
1278 #endif // !FEATURE_PAL
1279
1280 #ifdef _DEBUG
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
1287     // termination.
1288     //
1289     // This behavior can still be overridden if the right config value is set.
1290     if (IsDebuggerPresent())
1291     {
1292         bool fBreak = (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgOOBinFEEE) != 0);
1293
1294         if (fBreak)
1295         {
1296             DebugBreak();
1297         }
1298     }
1299 #endif // _DEBUG
1300
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)
1308     {
1309 #ifdef DEBUGGING_SUPPORTED
1310         //Give a managed debugger a chance if this fatal error is on a managed thread.
1311         Thread *pThread = GetThread();
1312
1313         if (pThread)
1314         {
1315             GCX_COOP();
1316
1317             OBJECTHANDLE ohException = NULL;
1318
1319             if (exitCode == (UINT)COR_E_STACKOVERFLOW)
1320             {
1321                 // If we're going down because of stack overflow, go ahead and use the preallocated SO exception.
1322                 ohException = CLRException::GetPreallocatedStackOverflowExceptionHandle();
1323             }
1324             else
1325             {
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();
1330             }
1331
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)
1335             {
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();
1340
1341                 if (exitCode == static_cast<UINT>(COR_E_FAILFAST) && lto != NULL)
1342                 {
1343                     EXCEPTIONREF curEx = (EXCEPTIONREF)ObjectFromHandle(ohException);
1344                     curEx->SetInnerException(lto);
1345                 }
1346                 pThread->SetLastThrownObject(ObjectFromHandle(ohException), TRUE);
1347             }
1348
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())
1352             {
1353                 pThread->GetExceptionState()->GetFlags()->SetDebuggerInterceptNotPossible();
1354             }
1355         }
1356
1357         if  (EXCEPTION_CONTINUE_EXECUTION == WatsonLastChance(pThread, pExceptionInfo, TypeOfReportedError::FatalError))
1358         {
1359             LOG((LF_EH, LL_INFO100, "EEPolicy::LogFatalError: debugger ==> EXCEPTION_CONTINUE_EXECUTION\n"));
1360             _ASSERTE(!"Debugger should not have returned ContinueExecution");
1361         }
1362 #endif // DEBUGGING_SUPPORTED
1363     }
1364 }
1365
1366 void DisplayStackOverflowException()
1367 {
1368     LIMITED_METHOD_CONTRACT;
1369     PrintToStdErrA("\n");
1370
1371     PrintToStdErrA("Process is terminating due to StackOverflowException.\n");
1372 }
1373
1374 void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pExceptionInfo, BOOL fSkipDebugger)
1375 {
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);
1379
1380     WRAPPER_NO_CONTRACT;
1381
1382     STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleFatalStackOverflow\n");
1383
1384     DisplayStackOverflowException();
1385
1386     if(ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, FailFast))
1387     {
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());
1394     }
1395
1396     if (!fSkipDebugger)
1397     {
1398         Thread *pThread = GetThread();
1399         BOOL fTreatAsNativeUnhandledException = FALSE;
1400         if (pThread)
1401         {
1402             GCX_COOP();
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 
1405             // NULL. 
1406             //
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();
1413             if (ohSO != NULL)
1414             {
1415                 pThread->SafeSetThrowables(ObjectFromHandle(ohSO) 
1416                                            DEBUG_ARG(ThreadExceptionState::STEC_CurrentTrackerEqualNullOkHackForFatalStackOverflow),
1417                                            TRUE);
1418             }
1419             else
1420             {
1421                 // We dont have a throwable - treat this as native unhandled exception
1422                 fTreatAsNativeUnhandledException = TRUE;
1423             }   
1424         }
1425         FrameWithCookie<FaultingExceptionFrame> fef;
1426 #if defined(WIN64EXCEPTIONS)
1427         *((&fef)->GetGSCookiePtr()) = GetProcessGSCookie();
1428 #endif // WIN64EXCEPTIONS
1429         if (pExceptionInfo && pExceptionInfo->ContextRecord)
1430         {
1431             GCX_COOP();
1432             fef.InitAndLink(pExceptionInfo->ContextRecord);
1433         }
1434
1435 #ifndef FEATURE_PAL        
1436         if (RunningOnWin7() && IsWatsonEnabled() && (g_pDebugInterface != NULL))
1437         {
1438             _ASSERTE(pExceptionInfo != NULL);
1439
1440             ResetWatsonBucketsParams param;
1441             param.m_pThread = pThread;
1442             param.pExceptionRecord = pExceptionInfo->ExceptionRecord;
1443             g_pDebugInterface->RequestFavor(ResetWatsonBucketsFavorWorker, reinterpret_cast<void *>(&param));
1444         }
1445 #endif // !FEATURE_PAL        
1446
1447         WatsonLastChance(pThread, pExceptionInfo, 
1448             (fTreatAsNativeUnhandledException == FALSE)? TypeOfReportedError::UnhandledException: TypeOfReportedError::NativeThreadUnhandledException);
1449     }
1450
1451     TerminateProcess(GetCurrentProcess(), COR_E_STACKOVERFLOW);
1452     UNREACHABLE();
1453 }
1454
1455 void DECLSPEC_NORETURN EEPolicy::HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage /* = NULL */, PEXCEPTION_POINTERS pExceptionInfo /* = NULL */)
1456 {
1457     WRAPPER_NO_CONTRACT;
1458
1459     // All of the code from here on out is robust to any failures in any API's that are called.
1460     FAULT_NOT_FATAL();
1461
1462     EXCEPTION_RECORD   exceptionRecord;
1463     EXCEPTION_POINTERS exceptionPointers;
1464     CONTEXT            context;
1465
1466     if (pExceptionInfo == NULL)
1467     {
1468         ZeroMemory(&exceptionPointers, sizeof(exceptionPointers));
1469         ZeroMemory(&exceptionRecord, sizeof(exceptionRecord));
1470         ZeroMemory(&context, sizeof(context));
1471         
1472         context.ContextFlags = CONTEXT_CONTROL;
1473         ClrCaptureContext(&context);
1474
1475         exceptionRecord.ExceptionCode = exitCode;
1476         exceptionRecord.ExceptionAddress = reinterpret_cast< PVOID >(address);
1477
1478         exceptionPointers.ExceptionRecord = &exceptionRecord;
1479         exceptionPointers.ContextRecord   = &context;
1480         pExceptionInfo = &exceptionPointers;
1481     }
1482
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.
1485     {
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);
1489
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()))
1495         {   
1496             ThreadSuspend::UnlockThreadStore();
1497         }
1498
1499         g_fFastExitProcess = 2;
1500
1501         STRESS_LOG0(LF_CORDB,LL_INFO100, "D::HFE: About to call LogFatalError\n");
1502         switch (GetEEPolicy()->GetActionOnFailure(FAIL_FatalRuntime))
1503         {
1504         case eRudeExitProcess:
1505             LogFatalError(exitCode, address, pszMessage, pExceptionInfo);
1506                 SafeExitProcess(exitCode, TRUE);
1507             break;
1508         case eDisableRuntime:
1509             LogFatalError(exitCode, address, pszMessage, pExceptionInfo);
1510             DisableRuntime(SCA_ExitProcessWhenShutdownComplete);
1511             break;
1512         default:
1513             _ASSERTE(!"Invalid action for FAIL_FatalRuntime");
1514             break;
1515         }
1516     }
1517
1518     UNREACHABLE();
1519 }
1520
1521 void EEPolicy::HandleExitProcessFromEscalation(EPolicyAction action, UINT exitCode)
1522 {
1523     WRAPPER_NO_CONTRACT;
1524     CONTRACT_VIOLATION(GCViolation); 
1525
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)
1531     {
1532         todo = action;
1533     }
1534     GetEEPolicy()->NotifyHostOnDefaultAction(OPR_ProcessExit,todo);
1535
1536     HandleExitProcessHelper(todo, exitCode, SCA_ExitProcessWhenShutdownComplete);
1537 }
1538
1539 void EEPolicy::HandleCodeContractFailure(LPCWSTR pMessage, LPCWSTR pCondition, LPCWSTR pInnerExceptionAsString)
1540 {
1541     WRAPPER_NO_CONTRACT;
1542
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();
1548
1549     switch(action) {
1550     case eThrowException:
1551         // Let managed code throw a ContractException (it's easier to pass the right parameters to the constructor).
1552         break;
1553     case eAbortThread:
1554         pThread->UserAbort(Thread::TAR_Thread, TA_Safe, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
1555         break;
1556     case eRudeAbortThread:
1557         pThread->UserAbort(Thread::TAR_Thread, TA_Rude, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
1558         break;
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);
1564         break;
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);
1571         break;
1572
1573     case eExitProcess:  // Merged w/ default case
1574     default:
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.
1579 #ifndef FEATURE_PAL        
1580         pThread->GetExceptionState()->GetUEWatsonBucketTracker()->ClearWatsonBucketDetails();
1581 #endif // !FEATURE_PAL
1582         pPolicy->HandleFatalError(COR_E_CODECONTRACTFAILED, NULL, pMessage);
1583         break;
1584     }
1585 }
1586