diff options
author | Aaron Robinson <arobins@microsoft.com> | 2019-05-29 23:51:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-29 23:51:51 -0700 |
commit | 5d16005b984b9b27ce59245bca87aa225b2ca0b7 (patch) | |
tree | 88bc97b2cdcbe4cd8afd509908dfe7cee609f599 | |
parent | e46ae5921c510309f252af21c2a88d341e4e15ab (diff) | |
download | coreclr-5d16005b984b9b27ce59245bca87aa225b2ca0b7.tar.gz coreclr-5d16005b984b9b27ce59245bca87aa225b2ca0b7.tar.bz2 coreclr-5d16005b984b9b27ce59245bca87aa225b2ca0b7.zip |
Remove all uses of CanRunManagedCode() (#24847)
* Remove all uses of CanRunManagedCode()
-rw-r--r-- | src/vm/ceemain.cpp | 166 | ||||
-rw-r--r-- | src/vm/clrex.h | 66 | ||||
-rw-r--r-- | src/vm/comcallablewrapper.cpp | 241 | ||||
-rw-r--r-- | src/vm/comcallablewrapper.h | 5 | ||||
-rw-r--r-- | src/vm/comtoclrcall.cpp | 29 | ||||
-rw-r--r-- | src/vm/corhost.cpp | 4 | ||||
-rw-r--r-- | src/vm/dllimportcallback.cpp | 19 | ||||
-rw-r--r-- | src/vm/excep.cpp | 25 | ||||
-rw-r--r-- | src/vm/excep.h | 4 | ||||
-rw-r--r-- | src/vm/i386/cgenx86.cpp | 16 | ||||
-rw-r--r-- | src/vm/runtimeexceptionkind.h | 10 | ||||
-rw-r--r-- | src/vm/stdinterfaces_wrapper.cpp | 66 | ||||
-rw-r--r-- | src/vm/threads.cpp | 11 | ||||
-rw-r--r-- | src/vm/util.cpp | 5 | ||||
-rw-r--r-- | src/vm/util.hpp | 51 | ||||
-rw-r--r-- | src/vm/vars.hpp | 18 |
16 files changed, 177 insertions, 559 deletions
diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index 03d492b063..6856d481cd 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -1180,95 +1180,6 @@ void ForceEEShutdown(ShutdownCompleteAction sca) } //--------------------------------------------------------------------------- -// %%Function: ExternalShutdownHelper -// -// Parameters: -// int exitCode :: process exit code -// ShutdownCompleteAction sca :: indicates whether ::ExitProcess() is -// called or if the function returns. -// -// Returns: -// Nothing -// -// Description: -// This is a helper shared by CorExitProcess and ShutdownRuntimeWithoutExiting -// which causes the runtime to shutdown after the appropriate checks. -// --------------------------------------------------------------------------- -static void ExternalShutdownHelper(int exitCode, ShutdownCompleteAction sca) -{ - CONTRACTL { - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - ENTRY_POINT; - } CONTRACTL_END; - - CONTRACT_VIOLATION(GCViolation | ModeViolation); - - if (g_fEEShutDown || !g_fEEStarted) - return; - - if (!CanRunManagedCode()) - { - return; - } - - // The exit code for the process is communicated in one of two ways. If the - // entrypoint returns an 'int' we take that. Otherwise we take a latched - // process exit code. This can be modified by the app via System.SetExitCode(). - SetLatchedExitCode(exitCode); - - - ForceEEShutdown(sca); - - // @TODO: If we cannot run ManagedCode, BEGIN_EXTERNAL_ENTRYPOINT will skip - // the shutdown. We could call ::ExitProcess in that failure case, but that - // would violate our hosting agreement. We are supposed to go through EEPolicy:: - // HandleExitProcess(). Is this legal if !CanRunManagedCode()? - -} - -//--------------------------------------------------------------------------- -// %%Function: void STDMETHODCALLTYPE CorExitProcess(int exitCode) -// -// Parameters: -// int exitCode :: process exit code -// -// Returns: -// Nothing -// -// Description: -// COM Objects shutdown stuff should be done here -// --------------------------------------------------------------------------- -extern "C" void STDMETHODCALLTYPE CorExitProcess(int exitCode) -{ - WRAPPER_NO_CONTRACT; - - ExternalShutdownHelper(exitCode, SCA_ExitProcessWhenShutdownComplete); -} - -//--------------------------------------------------------------------------- -// %%Function: ShutdownRuntimeWithoutExiting -// -// Parameters: -// int exitCode :: process exit code -// -// Returns: -// Nothing -// -// Description: -// This is a helper used only by the v4+ Shim to shutdown this runtime and -// and return when the work has completed. It is exposed to the Shim via -// GetCLRFunction. -// --------------------------------------------------------------------------- -void ShutdownRuntimeWithoutExiting(int exitCode) -{ - WRAPPER_NO_CONTRACT; - - ExternalShutdownHelper(exitCode, SCA_ReturnWhenShutdownComplete); -} - -//--------------------------------------------------------------------------- // %%Function: IsRuntimeStarted // // Parameters: @@ -1906,85 +1817,12 @@ void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading) // // Description: Indicates if the runtime is active or not. "Active" implies // that the runtime has started and is in a position to run -// managed code. If either of these conditions are false, the -// function return FALSE. -// -// Why couldnt we add !g_fEEStarted check in CanRunManagedCode? -// -// -// ExecuteDLL in ceemain.cpp could start the runtime -// (due to DLL_PROCESS_ATTACH) after invoking CanRunManagedCode. -// If the function were to be modified, then this scenario could fail. -// Hence, I have built over CanRunManagedCode in IsRuntimeActive. - +// managed code. // --------------------------------------------------------------------------- BOOL IsRuntimeActive() { - // If the runtime has started AND we can run managed code, - // then runtime is considered "active". - BOOL fCanRunManagedCode = CanRunManagedCode(); - return (g_fEEStarted && fCanRunManagedCode); -} - -// --------------------------------------------------------------------------- -// %%Function: CanRunManagedCode() -// -// Parameters: -// none -// -// Returns: -// true or false -// -// Description: Indicates if one is currently allowed to run managed code. -// --------------------------------------------------------------------------- -NOINLINE BOOL CanRunManagedCodeRare(LoaderLockCheck::kind checkKind, HINSTANCE hInst /*= 0*/) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - // If we are shutting down the runtime, then we cannot run code. - if (g_fForbidEnterEE) - return FALSE; - - // If pre-loaded objects are not present, then no way. - if (g_pPreallocatedOutOfMemoryException == NULL) - return FALSE; - - // If we are finaling live objects or processing ExitProcess event, - // we can not allow managed method to run unless the current thread - // is the finalizer thread - if ((g_fEEShutDown & ShutDown_Finalize2) && !FinalizerThread::IsCurrentThreadFinalizer()) - return FALSE; - - return TRUE; -} - -#include <optsmallperfcritical.h> -BOOL CanRunManagedCode(LoaderLockCheck::kind checkKind, HINSTANCE hInst /*= 0*/) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - // Special-case the common success cases - // (Try not to make any calls here so that we don't have to spill our incoming arg regs) - if (!g_fForbidEnterEE - && (g_pPreallocatedOutOfMemoryException != NULL) - && !(g_fEEShutDown & ShutDown_Finalize2) - && ((checkKind == LoaderLockCheck::None))) - { - return TRUE; - } - - // Then call a helper for everything else. - return CanRunManagedCodeRare(checkKind, hInst); + return (g_fEEStarted); } -#include <optdefault.h> //***************************************************************************** BOOL ExecuteDLL_ReturnOrThrow(HRESULT hr, BOOL fFromThunk) diff --git a/src/vm/clrex.h b/src/vm/clrex.h index 040ad2c8f6..e8ef895e9d 100644 --- a/src/vm/clrex.h +++ b/src/vm/clrex.h @@ -971,47 +971,39 @@ LONG CLRNoCatchHandler(EXCEPTION_POINTERS* pExceptionInfo, PVOID pv); // outside unmanaged code. If you want to connect internal pieces // of CLR code, use EX_TRY instead. //=================================================================================== -#define BEGIN_EXTERNAL_ENTRYPOINT(phresult) \ - { \ - HRESULT *__phr = (phresult); \ - *__phr = S_OK; \ - _ASSERTE(GetThread() == NULL || \ - !GetThread()->PreemptiveGCDisabled()); \ - if (!CanRunManagedCode()) \ - { \ - *__phr = E_PROCESS_SHUTDOWN_REENTRY; \ - } \ - else \ - { \ - MAKE_CURRENT_THREAD_AVAILABLE_EX(GetThreadNULLOk()); \ - if (CURRENT_THREAD == NULL) \ - { \ - CURRENT_THREAD = SetupThreadNoThrow(__phr); \ - } \ - if (CURRENT_THREAD != NULL) \ - { \ - EX_TRY_THREAD(CURRENT_THREAD); \ - { \ - -#define END_EXTERNAL_ENTRYPOINT \ - } \ - EX_CATCH_HRESULT(*__phr); \ - } \ - } \ - } \ +#define BEGIN_EXTERNAL_ENTRYPOINT(phresult) \ + { \ + HRESULT *__phr = (phresult); \ + *__phr = S_OK; \ + _ASSERTE(GetThread() == NULL || \ + !GetThread()->PreemptiveGCDisabled()); \ + MAKE_CURRENT_THREAD_AVAILABLE_EX(GetThreadNULLOk()); \ + if (CURRENT_THREAD == NULL) \ + { \ + CURRENT_THREAD = SetupThreadNoThrow(__phr); \ + } \ + if (CURRENT_THREAD != NULL) \ + { \ + EX_TRY_THREAD(CURRENT_THREAD); \ + { \ + +#define END_EXTERNAL_ENTRYPOINT \ + } \ + EX_CATCH_HRESULT(*__phr); \ + } \ + } \ // This macro should be used at the entry points (e.g. COM interop boundaries) // where CE's are not expected to get swallowed. #define END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS_EX(fCond) \ - } \ - EX_CATCH \ - { \ - *__phr = GET_EXCEPTION()->GetHR(); \ - } \ - EX_END_CATCH(RethrowCorruptingExceptionsEx(fCond)); \ - } \ - } \ - } \ + } \ + EX_CATCH \ + { \ + *__phr = GET_EXCEPTION()->GetHR(); \ + } \ + EX_END_CATCH(RethrowCorruptingExceptionsEx(fCond)); \ + } \ + } \ // This macro should be used at the entry points (e.g. COM interop boundaries) // where CE's are not expected to get swallowed. diff --git a/src/vm/comcallablewrapper.cpp b/src/vm/comcallablewrapper.cpp index d271a6dd22..7addbfda9c 100644 --- a/src/vm/comcallablewrapper.cpp +++ b/src/vm/comcallablewrapper.cpp @@ -445,80 +445,104 @@ extern "C" PCODE ComPreStubWorker(ComPrestubMethodFrame *pPFrame, UINT64 *pError OBJECTREF pThrowable = NULL; - if (!CanRunManagedCode()) + Thread* pThread = SetupThreadNoThrow(); + if (pThread == NULL) { - hr = E_PROCESS_SHUTDOWN_REENTRY; + hr = E_OUTOFMEMORY; } else { - Thread* pThread = SetupThreadNoThrow(); - if (pThread == NULL) - { - hr = E_OUTOFMEMORY; - } - else - { - // Transition to cooperative GC mode before we start setting up the stub. - GCX_COOP(); + // Transition to cooperative GC mode before we start setting up the stub. + GCX_COOP(); - // The PreStub allocates memory for the frame, but doesn't link it - // into the chain or fully initialize it. Do so now. - pPFrame->Init(); - pPFrame->Push(); + // The PreStub allocates memory for the frame, but doesn't link it + // into the chain or fully initialize it. Do so now. + pPFrame->Init(); + pPFrame->Push(); - ComCallWrapper *pWrap = NULL; + ComCallWrapper *pWrap = NULL; - GCPROTECT_BEGIN(pThrowable) + GCPROTECT_BEGIN(pThrowable) + { + // We need a try/catch around the code to enter the domain since entering + // an AppDomain can throw an exception. + EX_TRY { - // We need a try/catch around the code to enter the domain since entering - // an AppDomain can throw an exception. - EX_TRY - { - // check for invalid wrappers in the debug build - // in the retail all bets are off - pWrap = ComCallWrapper::GetWrapperFromIP(pUnk); - _ASSERTE(pWrap->IsWrapperActive() || pWrap->IsAggregated()); - - // Make sure we're not trying to call on the class interface of a class with ComVisible(false) members - // in its hierarchy. - if ((pCMD->IsFieldCall()) || (NULL == pCMD->GetInterfaceMethodDesc() && !pCMD->GetMethodDesc()->IsInterface())) - { - // If we have a fieldcall or a null interface MD, we could be dealing with the IClassX interface. - ComMethodTable* pComMT = ComMethodTable::ComMethodTableFromIP(pUnk); - pComMT->CheckParentComVisibility(FALSE); - } - - { - OBJECTREF pADThrowable = NULL; + // check for invalid wrappers in the debug build + // in the retail all bets are off + pWrap = ComCallWrapper::GetWrapperFromIP(pUnk); + _ASSERTE(pWrap->IsWrapperActive() || pWrap->IsAggregated()); + + // Make sure we're not trying to call on the class interface of a class with ComVisible(false) members + // in its hierarchy. + if ((pCMD->IsFieldCall()) || (NULL == pCMD->GetInterfaceMethodDesc() && !pCMD->GetMethodDesc()->IsInterface())) + { + // If we have a fieldcall or a null interface MD, we could be dealing with the IClassX interface. + ComMethodTable* pComMT = ComMethodTable::ComMethodTableFromIP(pUnk); + pComMT->CheckParentComVisibility(FALSE); + } - BOOL fExceptionThrown = FALSE; + { + OBJECTREF pADThrowable = NULL; - GCPROTECT_BEGIN(pADThrowable); + BOOL fExceptionThrown = FALSE; + + GCPROTECT_BEGIN(pADThrowable); + { + if (pCMD->IsMethodCall()) { - if (pCMD->IsMethodCall()) + // We need to ensure all valuetypes are loaded in + // the target domain so that GC can happen later + + EX_TRY { - // We need to ensure all valuetypes are loaded in - // the target domain so that GC can happen later - - EX_TRY - { - MethodDesc* pTargetMD = pCMD->GetMethodDesc(); - MetaSig::EnsureSigValueTypesLoaded(pTargetMD); - - if (pCMD->IsWinRTCtor() || pCMD->IsWinRTStatic() || pCMD->IsWinRTRedirectedMethod()) - { - // Activation, static method invocation, and call through a redirected interface may be the first - // managed code that runs in the module. Fully load it here so we don't have to call EnsureInstanceActive - // on every activation/static call. - pTargetMD->GetMethodTable()->EnsureInstanceActive(); - } - } - EX_CATCH + MethodDesc* pTargetMD = pCMD->GetMethodDesc(); + MetaSig::EnsureSigValueTypesLoaded(pTargetMD); + + if (pCMD->IsWinRTCtor() || pCMD->IsWinRTStatic() || pCMD->IsWinRTRedirectedMethod()) { - pADThrowable = GET_THROWABLE(); + // Activation, static method invocation, and call through a redirected interface may be the first + // managed code that runs in the module. Fully load it here so we don't have to call EnsureInstanceActive + // on every activation/static call. + pTargetMD->GetMethodTable()->EnsureInstanceActive(); } - EX_END_CATCH(RethrowTerminalExceptions); } + EX_CATCH + { + pADThrowable = GET_THROWABLE(); + } + EX_END_CATCH(RethrowTerminalExceptions); + } + + if (pADThrowable != NULL) + { + // Transform the exception into an HRESULT. This also sets up + // an IErrorInfo on the current thread for the exception. + hr = SetupErrorInfo(pADThrowable, pCMD); + pADThrowable = NULL; + fExceptionThrown = TRUE; + } + } + GCPROTECT_END(); + + if(!fExceptionThrown) + { + GCPROTECT_BEGIN(pADThrowable); + { + // We need a try/catch around the call to the worker since we need + // to transform any exceptions into HRESULTs. We want to do this + // inside the AppDomain of the CCW. + EX_TRY + { + GCX_PREEMP(); + pStub = ComCall::GetComCallMethodStub(pCMD); + } + EX_CATCH + { + fNonTransientExceptionThrown = !GET_EXCEPTION()->IsTransient(); + pADThrowable = GET_THROWABLE(); + } + EX_END_CATCH(RethrowTerminalExceptions); if (pADThrowable != NULL) { @@ -526,85 +550,54 @@ extern "C" PCODE ComPreStubWorker(ComPrestubMethodFrame *pPFrame, UINT64 *pError // an IErrorInfo on the current thread for the exception. hr = SetupErrorInfo(pADThrowable, pCMD); pADThrowable = NULL; - fExceptionThrown = TRUE; } } GCPROTECT_END(); - - if(!fExceptionThrown) - { - GCPROTECT_BEGIN(pADThrowable); - { - // We need a try/catch around the call to the worker since we need - // to transform any exceptions into HRESULTs. We want to do this - // inside the AppDomain of the CCW. - EX_TRY - { - GCX_PREEMP(); - pStub = ComCall::GetComCallMethodStub(pCMD); - } - EX_CATCH - { - fNonTransientExceptionThrown = !GET_EXCEPTION()->IsTransient(); - pADThrowable = GET_THROWABLE(); - } - EX_END_CATCH(RethrowTerminalExceptions); - - if (pADThrowable != NULL) - { - // Transform the exception into an HRESULT. This also sets up - // an IErrorInfo on the current thread for the exception. - hr = SetupErrorInfo(pADThrowable, pCMD); - pADThrowable = NULL; - } - } - GCPROTECT_END(); - } } } - EX_CATCH - { - pThrowable = GET_THROWABLE(); - - // If an exception was thrown while transitionning back to the original - // AppDomain then can't use the stub and must report an error. - pStub = NULL; - } - EX_END_CATCH(SwallowAllExceptions); - - if (pThrowable != NULL) - { - // Transform the exception into an HRESULT. This also sets up - // an IErrorInfo on the current thread for the exception. - hr = SetupErrorInfo(pThrowable, pCMD); - pThrowable = NULL; - } } - GCPROTECT_END(); + EX_CATCH + { + pThrowable = GET_THROWABLE(); - // Unlink the PrestubMethodFrame. - pPFrame->Pop(); + // If an exception was thrown while transitionning back to the original + // AppDomain then can't use the stub and must report an error. + pStub = NULL; + } + EX_END_CATCH(SwallowAllExceptions); - if (pStub) + if (pThrowable != NULL) { - // Now, replace the prestub with the new stub. - static_assert((COMMETHOD_CALL_PRESTUB_SIZE - COMMETHOD_CALL_PRESTUB_ADDRESS_OFFSET) % DATA_ALIGNMENT == 0, - "The call target in COM prestub must be aligned so we can guarantee atomicity of updates"); + // Transform the exception into an HRESULT. This also sets up + // an IErrorInfo on the current thread for the exception. + hr = SetupErrorInfo(pThrowable, pCMD); + pThrowable = NULL; + } + } + GCPROTECT_END(); + + // Unlink the PrestubMethodFrame. + pPFrame->Pop(); + + if (pStub) + { + // Now, replace the prestub with the new stub. + static_assert((COMMETHOD_CALL_PRESTUB_SIZE - COMMETHOD_CALL_PRESTUB_ADDRESS_OFFSET) % DATA_ALIGNMENT == 0, + "The call target in COM prestub must be aligned so we can guarantee atomicity of updates"); + + UINT_PTR* ppofs = (UINT_PTR*) (((BYTE*)pCMD) - COMMETHOD_CALL_PRESTUB_SIZE + COMMETHOD_CALL_PRESTUB_ADDRESS_OFFSET); - UINT_PTR* ppofs = (UINT_PTR*) (((BYTE*)pCMD) - COMMETHOD_CALL_PRESTUB_SIZE + COMMETHOD_CALL_PRESTUB_ADDRESS_OFFSET); - - *ppofs = ((UINT_PTR)pStub #ifdef _TARGET_X86_ - - (size_t)pCMD + *ppofs = ((UINT_PTR)pStub - (size_t)pCMD); +#else + *ppofs = ((UINT_PTR)pStub); #endif - ); - // Return the address of the prepad. The prepad will regenerate the hidden parameter and due - // to the update above will execute the new stub code the second time around. - retAddr = (PCODE)(((BYTE*)pCMD - COMMETHOD_CALL_PRESTUB_SIZE)ARM_ONLY(+THUMB_CODE)); + // Return the address of the prepad. The prepad will regenerate the hidden parameter and due + // to the update above will execute the new stub code the second time around. + retAddr = (PCODE)(((BYTE*)pCMD - COMMETHOD_CALL_PRESTUB_SIZE)ARM_ONLY(+THUMB_CODE)); - goto Exit; - } + goto Exit; } } diff --git a/src/vm/comcallablewrapper.h b/src/vm/comcallablewrapper.h index 104d7ec6fa..53addfaf20 100644 --- a/src/vm/comcallablewrapper.h +++ b/src/vm/comcallablewrapper.h @@ -1717,7 +1717,7 @@ public: } CONTRACTL_END; - SetupForComCallHRNoHostNotifNoCheckCanRunManagedCode(); + SetupForComCallHR(); // we can safely assume that the CCW is still alive since this is an AddRef StackSString ssMessage; @@ -1782,9 +1782,6 @@ private: } CONTRACTL_END; - if (!CanRunManagedCode()) - return; - m_pWrap->Cleanup(); } public: diff --git a/src/vm/comtoclrcall.cpp b/src/vm/comtoclrcall.cpp index 362759a000..033dfddcdf 100644 --- a/src/vm/comtoclrcall.cpp +++ b/src/vm/comtoclrcall.cpp @@ -136,30 +136,19 @@ extern "C" HRESULT STDCALL StubRareDisableHRWorker(Thread *pThread) // dangerous mode. If we call managed code, we will potentially be active in // the GC heap, even as GC's are occuring! - // Check for ShutDown scenario. This happens only when we have initiated shutdown - // and someone is trying to call in after the CLR is suspended. In that case, we - // must either raise an unmanaged exception or return an HRESULT, depending on the - // expectations of our caller. - if (!CanRunManagedCode()) + // We must do the following in this order, because otherwise we would be constructing + // the exception for the abort without synchronizing with the GC. Also, we have no + // CLR SEH set up, despite the fact that we may throw a ThreadAbortException. + pThread->RareDisablePreemptiveGC(); + EX_TRY { - hr = E_PROCESS_SHUTDOWN_REENTRY; + pThread->HandleThreadAbort(); } - else + EX_CATCH { - // We must do the following in this order, because otherwise we would be constructing - // the exception for the abort without synchronizing with the GC. Also, we have no - // CLR SEH set up, despite the fact that we may throw a ThreadAbortException. - pThread->RareDisablePreemptiveGC(); - EX_TRY - { - pThread->HandleThreadAbort(); - } - EX_CATCH - { - hr = GET_EXCEPTION()->GetHR(); - } - EX_END_CATCH(SwallowAllExceptions); + hr = GET_EXCEPTION()->GetHR(); } + EX_END_CATCH(SwallowAllExceptions); // should always be in coop mode here _ASSERTE(pThread->PreemptiveGCDisabled()); diff --git a/src/vm/corhost.cpp b/src/vm/corhost.cpp index 5ddaa7754c..be91820e6c 100644 --- a/src/vm/corhost.cpp +++ b/src/vm/corhost.cpp @@ -271,9 +271,7 @@ HRESULT CorHost2::GetCurrentAppDomainId(DWORD *pdwAppDomainId) CONTRACTL_END; // No point going further if the runtime is not running... - // We use CanRunManagedCode() instead of IsRuntimeActive() because this allows us - // to specify test using the form that does not trigger a GC. - if (!(g_fEEStarted && CanRunManagedCode(LoaderLockCheck::None))) + if (!IsRuntimeActive()) { return HOST_E_CLRNOTAVAILABLE; } diff --git a/src/vm/dllimportcallback.cpp b/src/vm/dllimportcallback.cpp index 806295d8bc..b5a4c9c4d7 100644 --- a/src/vm/dllimportcallback.cpp +++ b/src/vm/dllimportcallback.cpp @@ -852,8 +852,7 @@ extern "C" VOID STDCALL UMThunkStubRareDisableWorker(Thread *pThread, UMEntryThu STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; - // Do not add a CONTRACT here. We haven't set up SEH. We rely - // on HandleThreadAbort and COMPlusThrowBoot dealing with this situation properly. + // Do not add a CONTRACT here. We haven't set up SEH. // WARNING!!!! // when we start executing here, we are actually in cooperative mode. But we @@ -861,19 +860,6 @@ extern "C" VOID STDCALL UMThunkStubRareDisableWorker(Thread *pThread, UMEntryThu // dangerous mode. If we call managed code, we will potentially be active in // the GC heap, even as GC's are occuring! - // Check for ShutDown scenario. This happens only when we have initiated shutdown - // and someone is trying to call in after the CLR is suspended. In that case, we - // must either raise an unmanaged exception or return an HRESULT, depending on the - // expectations of our caller. - if (!CanRunManagedCode()) - { - // DO NOT IMPROVE THIS EXCEPTION! It cannot be a managed exception. It - // cannot be a real exception object because we cannot execute any managed - // code here. - pThread->m_fPreemptiveGCDisabled = 0; - COMPlusThrowBoot(E_PROCESS_SHUTDOWN_REENTRY); - } - // We must do the following in this order, because otherwise we would be constructing // the exception for the abort without synchronizing with the GC. Also, we have no // CLR SEH set up, despite the fact that we may throw a ThreadAbortException. @@ -897,9 +883,6 @@ PCODE TheUMEntryPrestubWorker(UMEntryThunk * pUMEntryThunk) STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_PREEMPTIVE; - if (!CanRunManagedCode()) - COMPlusThrowBoot(E_PROCESS_SHUTDOWN_REENTRY); - Thread * pThread = GetThreadNULLOk(); if (pThread == NULL) pThread = CreateThreadBlockThrow(); diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 156a8e7424..15598af5fb 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -155,17 +155,6 @@ BOOL NotifyAppDomainsOfUnhandledException( VOID SetManagedUnhandledExceptionBit( BOOL useLastThrownObject); - -void COMPlusThrowBoot(HRESULT hr) -{ - STATIC_CONTRACT_THROWS; - - _ASSERTE(g_fEEShutDown >= ShutDown_Finalize2 || !"This should not be called unless we are in the last phase of shutdown!"); - ULONG_PTR arg = hr; - RaiseException(BOOTUP_EXCEPTION_COMPLUS, EXCEPTION_NONCONTINUABLE, 1, &arg); -} - - //------------------------------------------------------------------------------- // This simply tests to see if the exception object is a subclass of // the descriminating class specified in the exception clause. @@ -5469,11 +5458,6 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, PrintToStdErrA(" StackOverflowException.\n"); } } - else if (!CanRunManagedCode(LoaderLockCheck::None)) - { - // Well, if we can't enter the runtime, we very well can't get the exception message. - dump = FALSE; - } else if (SentEvent || IsAsyncThreadException(&throwable)) { // We don't print anything on async exceptions, like ThreadAbort. @@ -5609,20 +5593,13 @@ BOOL NotifyAppDomainsOfUnhandledException( #endif GCPROTECT_BEGIN(throwable); - //BOOL IsStackOverflow = (throwable->GetMethodTable() == g_pStackOverflowExceptionClass); // Notify the AppDomain that we have taken an unhandled exception. Can't notify of stack overflow -- guard // page is not yet reset. // Send up the unhandled exception appdomain event. - // - // If we can't run managed code, we can't deliver the event. Nor do we attempt to delieve the event in stack - // overflow or OOM conditions. - if (/*!IsStackOverflow &&*/ - pThread->DetermineIfGuardPagePresent() && - CanRunManagedCode(LoaderLockCheck::None)) + if (pThread->DetermineIfGuardPagePresent()) { - // x86 only #if !defined(WIN64EXCEPTIONS) // If the Thread object's exception state's exception pointers diff --git a/src/vm/excep.h b/src/vm/excep.h index 9d8e5d2edb..d659b7cee0 100644 --- a/src/vm/excep.h +++ b/src/vm/excep.h @@ -566,13 +566,9 @@ void VerifyValidTransitionFromManagedCode(Thread *pThread, CrawlFrame *pCF); // This is a workaround designed to allow the use of the StubLinker object at bootup // time where the EE isn't sufficient awake to create COM+ exception objects. // Instead, COMPlusThrow(rexcep) does a simple RaiseException using this code. -// Or use COMPlusThrowBoot() to explicitly do so. //========================================================================== #define BOOTUP_EXCEPTION_COMPLUS 0xC0020001 -void COMPlusThrowBoot(HRESULT hr); - - //========================================================================== // Used by the classloader to record a managed exception object to explain // why a classload got botched. diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp index a5a85b0481..9b51e4db95 100644 --- a/src/vm/i386/cgenx86.cpp +++ b/src/vm/i386/cgenx86.cpp @@ -1051,8 +1051,7 @@ extern "C" VOID STDCALL StubRareDisableTHROWWorker(Thread *pThread) STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; - // Do not add a CONTRACT here. We haven't set up SEH. We rely - // on HandleThreadAbort and COMPlusThrowBoot dealing with this situation properly. + // Do not add a CONTRACT here. We haven't set up SEH. // WARNING!!!! // when we start executing here, we are actually in cooperative mode. But we @@ -1060,19 +1059,6 @@ extern "C" VOID STDCALL StubRareDisableTHROWWorker(Thread *pThread) // dangerous mode. If we call managed code, we will potentially be active in // the GC heap, even as GC's are occuring! - // Check for ShutDown scenario. This happens only when we have initiated shutdown - // and someone is trying to call in after the CLR is suspended. In that case, we - // must either raise an unmanaged exception or return an HRESULT, depending on the - // expectations of our caller. - if (!CanRunManagedCode()) - { - // DO NOT IMPROVE THIS EXCEPTION! It cannot be a managed exception. It - // cannot be a real exception object because we cannot execute any managed - // code here. - pThread->m_fPreemptiveGCDisabled = 0; - COMPlusThrowBoot(E_PROCESS_SHUTDOWN_REENTRY); - } - // We must do the following in this order, because otherwise we would be constructing // the exception for the abort without synchronizing with the GC. Also, we have no // CLR SEH set up, despite the fact that we may throw a ThreadAbortException. diff --git a/src/vm/runtimeexceptionkind.h b/src/vm/runtimeexceptionkind.h index 7241c65830..6ed92f7ea8 100644 --- a/src/vm/runtimeexceptionkind.h +++ b/src/vm/runtimeexceptionkind.h @@ -4,9 +4,6 @@ // RuntimeExceptionKind.h // -// - - #ifndef __runtimeexceptionkind_h__ #define __runtimeexceptionkind_h__ @@ -21,11 +18,4 @@ enum RuntimeExceptionKind { kLastException }; - -// I would have preferred to define a unique HRESULT in our own facility, but we -// weren't supposed to create new HRESULTs so close to ship. And now it's set -// in stone. -#define E_PROCESS_SHUTDOWN_REENTRY HRESULT_FROM_WIN32(ERROR_PROCESS_ABORTED) - - #endif // __runtimeexceptionkind_h__ diff --git a/src/vm/stdinterfaces_wrapper.cpp b/src/vm/stdinterfaces_wrapper.cpp index a835ba0027..ad245c8264 100644 --- a/src/vm/stdinterfaces_wrapper.cpp +++ b/src/vm/stdinterfaces_wrapper.cpp @@ -616,24 +616,10 @@ ULONG __stdcall Unknown_ReleaseSpecial(IUnknown* pUnk) HRESULT __stdcall Unknown_QueryInterface_IErrorInfo(IUnknown* pUnk, REFIID riid, void** ppv) { - // Special version of SetupForComCallHR that doesn't call - // CanRunManagedCode() to avoid firing LoaderLock MDA - SetupForComCallHRNoCheckCanRunManagedCode(); + SetupForComCallHR(); WRAPPER_NO_CONTRACT; - HRESULT hr = S_OK; - if (!CanRunManagedCode(LoaderLockCheck::ForCorrectness)) - { - // if we cannot run managed code, do a very simple QI which responds only to IUnknown and IErrorInfo - hr = Unknown_QueryInterface_IErrorInfo_Simple(pUnk, riid, ppv); - - if (hr == E_NOINTERFACE) - { - hr = HOST_E_CLRNOTAVAILABLE; - } - } - // otherwise do a regular QI return Unknown_QueryInterface(pUnk, riid, ppv); } @@ -644,29 +630,16 @@ HRESULT __stdcall Unknown_QueryInterface_IErrorInfo(IUnknown* pUnk, REFIID riid, // --------------------------------------------------------------------------- ULONG __stdcall Unknown_ReleaseSpecial_IErrorInfo(IUnknown* pUnk) { - // Special version of SetupForComCallDWORD that doesn't call - // CanRunManagedCode() to avoid firing LoaderLock MDA - // No managed code will be executed in this function - SetupForComCallDWORDNoCheckCanRunManagedCode(); + SetupForComCallDWORD(); WRAPPER_NO_CONTRACT; - // <TODO>Address this violation in context of bug 27409</TODO> CONTRACT_VIOLATION(GCViolation); - if (!CanRunManagedCode(LoaderLockCheck::None)) - { - // CCW cleanup doesn't run managed code but may trigger operations such as - // switching the thread to cooperative mode which is not safe during shutdown. - return 0; - } - else - { - // Don't switch domains since we need to allow release calls to go through - // even after the AD has been unlaoded. Furthermore release doesn't require - // us to transition into the domain to work properly. - return Unknown_ReleaseSpecial_IErrorInfo_Internal(pUnk); - } + // Don't switch domains since we need to allow release calls to go through + // even after the AD has been unlaoded. Furthermore release doesn't require + // us to transition into the domain to work properly. + return Unknown_ReleaseSpecial_IErrorInfo_Internal(pUnk); } @@ -1288,12 +1261,7 @@ HRESULT __stdcall Dispatch_Invoke_Wrapper(IDispatch* pDisp, DISPID dispidMember, { HRESULT hrRetVal = S_OK; -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - BeginSetupForComCallHRWithEscapingCorruptingExceptions(); -#else // !FEATURE_CORRUPTING_EXCEPTIONS SetupForComCallHR(); -#endif // FEATURE_CORRUPTING_EXCEPTIONS - CONTRACTL { @@ -1310,11 +1278,7 @@ HRESULT __stdcall Dispatch_Invoke_Wrapper(IDispatch* pDisp, DISPID dispidMember, InvokeArgs args = {pDisp, dispidMember, &riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr, &hrRetVal}; - Dispatch_Invoke_CallBack(&args); - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - EndSetupForComCallHRWithEscapingCorruptingExceptions(); -#endif // FEATURE_CORRUPTING_EXCEPTIONS + Dispatch_Invoke_CallBack(&args); return hrRetVal; } @@ -3001,8 +2965,7 @@ HRESULT __stdcall IStringable_ToString_Wrapper(IUnknown *pStringable, ULONG __stdcall ICCW_AddRefFromJupiter_Wrapper(IUnknown *pUnk) { - // We do not need to hook with host here - SetupForComCallDWORDNoHostNotif(); + SetupForComCallDWORD(); WRAPPER_NO_CONTRACT; @@ -3011,8 +2974,7 @@ ULONG __stdcall ICCW_AddRefFromJupiter_Wrapper(IUnknown *pUnk) ULONG __stdcall ICCW_ReleaseFromJupiter_Wrapper(IUnknown *pUnk) { - // We do not need to hook with host here - SetupForComCallDWORDNoHostNotif(); + SetupForComCallDWORD(); WRAPPER_NO_CONTRACT; @@ -3021,10 +2983,7 @@ ULONG __stdcall ICCW_ReleaseFromJupiter_Wrapper(IUnknown *pUnk) HRESULT __stdcall ICCW_Peg_Wrapper(IUnknown *pUnk) { - // We do not need to hook with host here and we cannot do CanRunManagedCode check - // as we are most likely in the middle of a GC - SetupForComCallHRNoHostNotifNoCheckCanRunManagedCode(); - + SetupForComCallHR(); WRAPPER_NO_CONTRACT; return ICCW_Peg(pUnk); @@ -3032,10 +2991,7 @@ HRESULT __stdcall ICCW_Peg_Wrapper(IUnknown *pUnk) HRESULT __stdcall ICCW_Unpeg_Wrapper(IUnknown *pUnk) { - // We do not need to hook with host here and we cannot do CanRunManagedCode check - // as we are most likely in the middle of a GC - SetupForComCallHRNoHostNotifNoCheckCanRunManagedCode(); - + SetupForComCallHR(); WRAPPER_NO_CONTRACT; return ICCW_Unpeg(pUnk); diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index 945cb3a601..269533ee79 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -1025,14 +1025,6 @@ Thread* WINAPI CreateThreadBlockThrow() Thread* pThread = NULL; BEGIN_ENTRYPOINT_THROWS; - if (!CanRunManagedCode()) - { - // CLR is shutting down - someone's DllMain detach event may be calling back into managed code. - // It is misleading to use our COM+ exception code, since this is not a managed exception. - ULONG_PTR arg = E_PROCESS_SHUTDOWN_REENTRY; - RaiseException(EXCEPTION_EXX, 0, 1, &arg); - } - HRESULT hr = S_OK; pThread = SetupThreadNoThrow(&hr); if (pThread == NULL) @@ -3395,7 +3387,8 @@ DWORD Thread::DoAppropriateWaitWorker(int countHandles, HANDLE *handles, BOOL wa // since fundamental parts of the system (such as the GC) rely on non alertable // waits not running any managed code. Also if we are past the point in shutdown were we // are allowed to run managed code then we can't forward the call to the sync context. - if (!ignoreSyncCtx && alertable && CanRunManagedCode(LoaderLockCheck::None) + if (!ignoreSyncCtx + && alertable && !HasThreadStateNC(Thread::TSNC_BlockedForShutdown)) { GCX_COOP(); diff --git a/src/vm/util.cpp b/src/vm/util.cpp index 0a21d3da6d..077b40926f 100644 --- a/src/vm/util.cpp +++ b/src/vm/util.cpp @@ -2057,7 +2057,6 @@ HMODULE CLRGetModuleHandle(LPCWSTR lpModuleFileName) LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes); BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem); -void ShutdownRuntimeWithoutExiting(int exitCode); BOOL IsRuntimeStarted(DWORD *pdwStartupFlags); void *GetCLRFunction(LPCSTR FunctionName) @@ -2076,10 +2075,6 @@ void *GetCLRFunction(LPCSTR FunctionName) { func = (void*)EEHeapFreeInProcessHeap; } - else if (strcmp(FunctionName, "ShutdownRuntimeWithoutExiting") == 0) - { - func = (void*)ShutdownRuntimeWithoutExiting; - } else if (strcmp(FunctionName, "IsRuntimeStarted") == 0) { func = (void*)IsRuntimeStarted; diff --git a/src/vm/util.hpp b/src/vm/util.hpp index 5d165e65b3..5d484f2ee4 100644 --- a/src/vm/util.hpp +++ b/src/vm/util.hpp @@ -744,55 +744,8 @@ void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX); return OOMRetVal; \ } \ - -#define InternalSetupForComCall(CannotEnterRetVal, OOMRetVal, SORetVal, CheckCanRunManagedCode) \ -SetupThreadForComCall(OOMRetVal); \ -if (CheckCanRunManagedCode && !CanRunManagedCode()) \ - return CannotEnterRetVal; - -#define SetupForComCallHRNoHostNotif() InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, true) -#define SetupForComCallHRNoHostNotifNoCheckCanRunManagedCode() InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, false) -#define SetupForComCallDWORDNoHostNotif() InternalSetupForComCall(-1, -1, -1, true) - -#define SetupForComCallHR() \ -InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, true) - -#define SetupForComCallHRNoCheckCanRunManagedCode() \ -InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, false) - -#ifdef FEATURE_CORRUPTING_EXCEPTIONS - -// Since Corrupting exceptions can escape COM interop boundaries, -// these macros will be used to setup the initial SO-Intolerant transition. -#define InternalSetupForComCallWithEscapingCorruptingExceptions(CannotEnterRetVal, OOMRetVal, SORetVal, CheckCanRunManagedCode) \ -if (CheckCanRunManagedCode && !CanRunManagedCode()) \ - return CannotEnterRetVal; \ -SetupThreadForComCall(OOMRetVal); \ - -#define BeginSetupForComCallHRWithEscapingCorruptingExceptions() \ -HRESULT __hr = S_OK; \ -InternalSetupForComCallWithEscapingCorruptingExceptions(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, true) \ - \ -if (SUCCEEDED(__hr)) \ -{ \ - -#define EndSetupForComCallHRWithEscapingCorruptingExceptions() \ -} \ - \ -if (FAILED(__hr)) \ -{ \ - return __hr; \ -} \ - -#endif // FEATURE_CORRUPTING_EXCEPTIONS - -#define SetupForComCallDWORD() \ -InternalSetupForComCall(-1, -1, -1, true) - -// Special version of SetupForComCallDWORD that doesn't call -// CanRunManagedCode() to avoid firing LoaderLock MDA -#define SetupForComCallDWORDNoCheckCanRunManagedCode() \ -InternalSetupForComCall(-1, -1, -1, false) +#define SetupForComCallHR() SetupThreadForComCall(E_OUTOFMEMORY) +#define SetupForComCallDWORD() SetupThreadForComCall(ERROR_OUTOFMEMORY) // A holder for NATIVE_LIBRARY_HANDLE. FORCEINLINE void VoidFreeNativeLibrary(NATIVE_LIBRARY_HANDLE h) diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp index 25d46c2cc0..403e2f6843 100644 --- a/src/vm/vars.hpp +++ b/src/vm/vars.hpp @@ -487,24 +487,6 @@ extern BOOL g_fEnableETW; BOOL IsRuntimeActive(); // -// Can we run managed code? -// -struct LoaderLockCheck -{ - enum kind - { - ForMDA, - ForCorrectness, - None, - }; -}; -BOOL CanRunManagedCode(LoaderLockCheck::kind checkKind, HINSTANCE hInst = 0); -inline BOOL CanRunManagedCode(HINSTANCE hInst = 0) -{ - return CanRunManagedCode(LoaderLockCheck::ForMDA, hInst); -} - -// // Global state variable indicating if the EE is in its init phase. // EXTERN bool g_fEEInit; |