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.h
9// ---------------------------------------------------------------------------
10
11
12#ifndef EEPOLICY_H_
13#define EEPOLICY_H_
14
15#include "vars.hpp"
16#include "corhost.h"
17#include "ceemain.h"
18
19extern "C" UINT_PTR STDCALL GetCurrentIP();
20
21enum StackOverflowDetector
22{
23 SOD_ManagedFrameHandler,
24 SOD_UnmanagedFrameHandler,
25 SOD_SOTolerantTransitor,
26 SOD_SOIntolerantTransitor,
27};
28
29// EEPolicy maintains actions for resource failure and timeout
30class EEPolicy
31{
32public:
33 enum ThreadAbortTypes
34 {
35 TA_None, // No Abort
36 // Abort at a safe spot: not having any lock, not inside finally, not inside catch
37 TA_Safe,
38 // Do we need this one?
39 TA_V1Compatible,
40 // Do not run user finally, no attention to lock count
41 TA_Rude
42 };
43
44 enum AppDomainUnloadTypes
45 {
46 ADU_Safe,
47 ADU_Rude
48 };
49
50 EEPolicy ();
51
52 HRESULT SetTimeout(EClrOperation operation, DWORD timeout);
53
54 DWORD GetTimeout(EClrOperation operation)
55 {
56 LIMITED_METHOD_CONTRACT;
57 _ASSERTE(static_cast<UINT>(operation) < MaxClrOperation);
58 return m_Timeout[operation];
59 }
60
61 HRESULT SetActionOnTimeout(EClrOperation operation, EPolicyAction action);
62 EPolicyAction GetActionOnTimeout(EClrOperation operation, Thread *pThread)
63 {
64 WRAPPER_NO_CONTRACT;
65 _ASSERTE(static_cast<UINT>(operation) < MaxClrOperation);
66 return GetFinalAction(m_ActionOnTimeout[operation], pThread);
67 }
68
69 void NotifyHostOnTimeout(EClrOperation operation, EPolicyAction action);
70
71 HRESULT SetTimeoutAndAction(EClrOperation operation, DWORD timeout, EPolicyAction action);
72
73 HRESULT SetDefaultAction(EClrOperation operation, EPolicyAction action);
74 EPolicyAction GetDefaultAction(EClrOperation operation, Thread *pThread)
75 {
76 WRAPPER_NO_CONTRACT;
77 _ASSERTE(static_cast<UINT>(operation) < MaxClrOperation);
78 return GetFinalAction(m_DefaultAction[operation], pThread);
79 }
80
81 void NotifyHostOnDefaultAction(EClrOperation operation, EPolicyAction action);
82
83 HRESULT SetActionOnFailure(EClrFailure failure, EPolicyAction action);
84
85 // Generally GetActionOnFailure should be used so that a host can get notification.
86 // But if we have notified host on the same failure, but we need to check escalation again,
87 // GetActionOnFailureNoHostNotification can be used.
88 EPolicyAction GetActionOnFailure(EClrFailure failure);
89 EPolicyAction GetActionOnFailureNoHostNotification(EClrFailure failure);
90
91 // get and set unhandled exception policy
92 HRESULT SetUnhandledExceptionPolicy(EClrUnhandledException policy)
93 {
94 LIMITED_METHOD_CONTRACT;
95 if (policy != eRuntimeDeterminedPolicy && policy != eHostDeterminedPolicy)
96 {
97 return E_INVALIDARG;
98 }
99 else
100 {
101 m_unhandledExceptionPolicy = policy;
102 return S_OK;
103 }
104 }
105 EClrUnhandledException GetUnhandledExceptionPolicy()
106 {
107 LIMITED_METHOD_CONTRACT;
108 return m_unhandledExceptionPolicy;
109 }
110
111 static EPolicyAction DetermineResourceConstraintAction(Thread *pThread);
112
113 static void PerformResourceConstraintAction(Thread *pThread, EPolicyAction action, UINT exitCode, BOOL haveStack);
114
115 static void HandleOutOfMemory();
116
117 static void HandleStackOverflow(StackOverflowDetector detector, void * pLimitFrame);
118
119 static void HandleSoftStackOverflow(BOOL fSkipDebugger = FALSE);
120
121 static void HandleStackOverflowAfterCatch();
122
123 static void HandleExitProcess(ShutdownCompleteAction sca = SCA_ExitProcessWhenShutdownComplete);
124
125 static void DECLSPEC_NORETURN HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pMessage=NULL, PEXCEPTION_POINTERS pExceptionInfo= NULL, LPCWSTR errorSource=NULL, LPCWSTR argExceptionString=NULL);
126
127 static void DECLSPEC_NORETURN HandleFatalStackOverflow(EXCEPTION_POINTERS *pException, BOOL fSkipDebugger = FALSE);
128
129 static void HandleExitProcessFromEscalation(EPolicyAction action, UINT exitCode);
130
131 static void HandleCodeContractFailure(LPCWSTR pMessage, LPCWSTR pCondition, LPCWSTR pInnerExceptionAsString);
132
133private:
134 DWORD m_Timeout[MaxClrOperation];
135 EPolicyAction m_ActionOnTimeout[MaxClrOperation];
136 EPolicyAction m_DefaultAction[MaxClrOperation];
137 EPolicyAction m_ActionOnFailure[MaxClrFailure];
138 EClrUnhandledException m_unhandledExceptionPolicy;
139
140 // TODO: Support multiple methods to set policy: hosting, config, managed api.
141
142 // Return BOOL if action is acceptable for operation.
143 BOOL IsValidActionForOperation(EClrOperation operation, EPolicyAction action);
144 BOOL IsValidActionForTimeout(EClrOperation operation, EPolicyAction action);
145 BOOL IsValidActionForFailure(EClrFailure failure, EPolicyAction action);
146 EPolicyAction GetFinalAction(EPolicyAction action, Thread *pThread);
147
148 static void LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, LPCWSTR argExceptionString=NULL);
149
150 // IMPORTANT NOTE: only the following two functions should be calling ExitProcessViaShim.
151 // - CorHost2::ExitProcess
152 // - SafeExitProcess
153 friend class CorHost2;
154 friend void SafeExitProcess(UINT , BOOL , ShutdownCompleteAction);
155
156 static void ExitProcessViaShim(UINT exitCode);
157};
158
159void InitEEPolicy();
160
161extern BYTE g_EEPolicyInstance[];
162
163inline EEPolicy* GetEEPolicy()
164{
165 return (EEPolicy*)&g_EEPolicyInstance;
166}
167
168extern void FinalizerThreadAbortOnTimeout();
169extern ULONGLONG GetObjFinalizeStartTime();
170
171//
172// Use EEPOLICY_HANDLE_FATAL_ERROR when you have a situtation where the Runtime's internal state would be
173// inconsistent if execution were allowed to continue. This will apply the proper host's policy for fatal
174// errors. Note: this call will never return.
175//
176// NOTE: make sure to use the macro instead of claling EEPolicy::HandleFatalError directly. The macro grabs the IP
177// of where you are calling this from, so we can log it to help when debugging these failures later.
178//
179
180// FailFast with specific error code
181#define EEPOLICY_HANDLE_FATAL_ERROR(_exitcode) EEPolicy::HandleFatalError(_exitcode, GetCurrentIP());
182
183// FailFast with specific error code and message (LPWSTR)
184#define EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(_exitcode, _message) EEPolicy::HandleFatalError(_exitcode, GetCurrentIP(), _message);
185
186// FailFast with specific error code and exception details
187#define EEPOLICY_HANDLE_FATAL_ERROR_USING_EXCEPTION_INFO(_exitcode, _pExceptionInfo) EEPolicy::HandleFatalError(_exitcode, GetCurrentIP(), NULL, _pExceptionInfo);
188
189// Failfast with specific error code, exception details, and debug info
190#define EEPOLICY_HANDLE_FATAL_ERROR_USING_EXCEPTION_AND_DEBUG_INFO(_exitcode, _pExceptionInfo, _isDebug) EEPolicy::HandleFatalError(_exitcode, GetCurrentIP(), NULL, _pExceptionInfo, _isDebug);
191
192#endif // EEPOLICY_H_
193