Remove all uses of CanRunManagedCode() (dotnet/coreclr#24847)
authorAaron Robinson <arobins@microsoft.com>
Thu, 30 May 2019 06:51:51 +0000 (23:51 -0700)
committerGitHub <noreply@github.com>
Thu, 30 May 2019 06:51:51 +0000 (23:51 -0700)
* Remove all uses of CanRunManagedCode()

Commit migrated from https://github.com/dotnet/coreclr/commit/5d16005b984b9b27ce59245bca87aa225b2ca0b7

16 files changed:
src/coreclr/src/vm/ceemain.cpp
src/coreclr/src/vm/clrex.h
src/coreclr/src/vm/comcallablewrapper.cpp
src/coreclr/src/vm/comcallablewrapper.h
src/coreclr/src/vm/comtoclrcall.cpp
src/coreclr/src/vm/corhost.cpp
src/coreclr/src/vm/dllimportcallback.cpp
src/coreclr/src/vm/excep.cpp
src/coreclr/src/vm/excep.h
src/coreclr/src/vm/i386/cgenx86.cpp
src/coreclr/src/vm/runtimeexceptionkind.h
src/coreclr/src/vm/stdinterfaces_wrapper.cpp
src/coreclr/src/vm/threads.cpp
src/coreclr/src/vm/util.cpp
src/coreclr/src/vm/util.hpp
src/coreclr/src/vm/vars.hpp

index 03d492b..6856d48 100644 (file)
@@ -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)
index 040ad2c..e8ef895 100644 (file)
@@ -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.
index d271a6d..7addbfd 100644 (file)
@@ -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;
         }
     }
 
index 104d7ec..53addfa 100644 (file)
@@ -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:
index 362759a..033dfdd 100644 (file)
@@ -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());
index 5ddaa77..be91820 100644 (file)
@@ -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;
     }   
index 806295d..b5a4c9c 100644 (file)
@@ -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();
index 156a8e7..15598af 100644 (file)
@@ -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
index 9d8e5d2..d659b7c 100644 (file)
@@ -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.
index a5a85b0..9b51e4d 100644 (file)
@@ -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.
index 7241c65..6ed92f7 100644 (file)
@@ -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__
index a835ba0..ad245c8 100644 (file)
@@ -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);
index 945cb3a..269533e 100644 (file)
@@ -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();
index 0a21d3d..077b409 100644 (file)
@@ -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;
index 5d165e6..5d484f2 100644 (file)
@@ -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)
index 25d46c2..403e2f6 100644 (file)
@@ -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;