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 // ===========================================================================
6 // ===========================================================================
11 // The CLR code base uses a hyperlink feature of the HyperAddin plugin for Visual Studio. If you don't see
12 // 'HyperAddin' in your Visual Studio menu bar you don't have this support. To get it type
14 // \\clrmain\tools\installCLRAddins
16 // After installing HyperAddin, your first run of VS should be as an administrator so HyperAddin can update
17 // some registry information.
19 // At this point the code: prefixes become hyperlinks in Visual Studio and life is good. See
20 // http://mswikis/clr/dev/Pages/CLR%20Team%20Commenting.aspx for more information
22 // There is a bug associated with Visual Studio where it does not recognise the hyperlink if there is a ::
23 // preceeding it on the same line. Since C++ uses :: as a namespace separator, this can often mean that the
24 // second hyperlink on a line does not work. To work around this it is better to use '.' instead of :: as
25 // the namespace separators in code: hyperlinks.
28 // #TableOfContents The .NET Runtime Table of contents
30 // This comment is mean to be a nexus that allows you to jump quickly to various interesting parts of the
33 // You can refer to product studio bugs using urls like the following
34 // * http://bugcheck/bugs/DevDivBugs/2320.asp
35 // * http://bugcheck/bugs/VSWhidbey/601210.asp
37 // Dev10 Bugs can be added with URLs like the following (for Dev10 bug 671409)
38 // * http://tkbgitvstfat01:8090/wi.aspx?id=671409
40 //*************************************************************************************************
42 // * Introduction to the runtime file:../../Documentation/botr/botr-faq.md
44 // #MajorDataStructures. The major data structures associated with the runtime are
45 // * code:Thread (see file:threads.h#ThreadClass) - the additional thread state the runtime needs.
46 // * code:AppDomain - The managed version of a process
47 // * code:Assembly - The unit of deployment and versioning (may be several DLLs but often is only one).
48 // * code:Module - represents a Module (DLL or EXE).
49 // * code:MethodTable - represents the 'hot' part of a type (needed during normal execution)
50 // * code:EEClass - represents the 'cold' part of a type (used during compilation, interop, ...)
51 // * code:MethodDesc - represents a Method
52 // * code:FieldDesc - represents a Field.
53 // * code:Object - represents a object on the GC heap allocated with code:Alloc
55 // * ECMA specifications
56 // * Partition I Concepts
57 // http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20I%20Architecture.doc
58 // * Partition II Meta Data
59 // http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20II%20Metadata.doc
61 // http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20III%20CIL.doc
63 // * Serge Liden (worked on the CLR and owned ILASM / ILDASM for a long time wrote a good book on IL
64 // * Expert .NET 2.0 IL Assembler http://www.amazon.com/Expert-NET-2-0-IL-Assembler/dp/1590596463
66 // * This is also a pretty nice overview of what the CLR is at
67 // http://msdn2.microsoft.com/en-us/netframework/aa497266.aspx
69 // * code:EEStartup - This routine must be called before any interesting runtime services are used. It is
70 // invoked as part of mscorwks's DllMain logic.
71 // * code:#EEShutDown - Code called before we shut down the EE.
73 // * file:..\inc\corhdr.h#ManagedHeader - From a data structure point of view, this is the entry point into
74 // the runtime. This is how all other data in the EXE are found.
76 // * code:ICorJitCompiler#EEToJitInterface - This is the interface from the the EE to the Just in time (JIT)
77 // compiler. The interface to the JIT is relatively simple (compileMethod), however the EE provides a
78 // rich set of callbacks so the JIT can get all the information it needs. See also
79 // file:../../Documentation/botr/ryujit-overview.md for general information on the JIT.
81 // * code:VirtualCallStubManager - This is the main class that implements interface dispatch
83 // * Precode - Every method needs entry point for other code to call even if that native code does not
84 // actually exist yet. To support this methods can have code:Precode that is an entry point that exists
85 // and will call the JIT compiler if the code does not yet exist.
87 // * NGEN - NGen stands for Native code GENeration and it is the runtime way of precompiling IL and IL
88 // Meta-data into native code and runtime data structures. At compilation time the most
89 // fundamental data structures is the code:ZapNode which represents something that needs to go into the
92 // * What is cooperative / preemtive mode ? file:threads.h#CooperativeMode and
93 // file:threads.h#SuspendingTheRuntime and file:../../Documentation/botr/threading.md
94 // * Garbage collection - file:gc.cpp#Overview and file:../../Documentation/botr/garbage-collection.md
95 // * code:AppDomain - The managed version of a process.
96 // * Calling Into the runtime (FCALLs QCalls) file:../../Documentation/botr/mscorlib.md
97 // * Exceptions - file:../../Documentation/botr/exceptions.md. The most important routine to start
98 // with is code:COMPlusFrameHandler which is the routine that we hook up to get called when an unmanaged
100 // * Assembly Loading file:../../Documentation/botr/type-loader.md
101 // * Profiling file:../../Documentation/botr/profiling.md and file:../../Documentation/botr/profilability.md
102 // * FCALLS QCALLS (calling into the runtime from managed code)
103 // file:../../Documentation/botr/mscorlib.md
104 // * Event Tracing for Windows
105 // * file:../inc/eventtrace.h#EventTracing -
106 // * This is the main file dealing with event tracing in CLR
107 // * The implementation of this class is available in file:eventtrace.cpp
108 // * file:../inc/eventtrace.h#CEtwTracer - This is the main class dealing with event tracing in CLR.
109 // Follow the link for more information on how this feature has been implemented
110 // * http://mswikis/clr/dev/Pages/CLR%20ETW%20Events%20Wiki.aspx - Follow the link for more information on how to
111 // use this instrumentation feature.
113 // ----------------------------------------------------------------------------------------------------
114 // Features in the runtime that have been given hyperlinks
116 // * code:Nullable#NullableFeature - the Nullable<T> type has special runtime semantics associated with
117 // boxing this describes this feature.
124 #include "clsload.hpp"
129 #include "dllimport.h"
131 #include "eeconfig.h"
132 #include "stublink.h"
133 #include "method.hpp"
137 #include "stackwalk.h"
138 #include "gcheaputilities.h"
139 #include "interoputil.h"
140 #include "fieldmarshaler.h"
141 #include "dbginterface.h"
142 #include "eedbginterfaceimpl.h"
143 #include "debugdebugger.h"
144 #include "cordbpriv.h"
145 #include "comdelegate.h"
146 #include "appdomain.hpp"
147 #include "eventtrace.h"
150 #include "olevariant.h"
151 #include "comcallablewrapper.h"
152 #include "apithreadstress.h"
154 #include "../dlls/mscorrc/resource.h"
156 #include "shimload.h"
157 #include "comthreadpool.h"
158 #include "posterror.h"
159 #include "virtualcallstub.h"
160 #include "strongnameinternal.h"
161 #include "syncclean.hpp"
162 #include "typeparse.h"
163 #include "debuginfostore.h"
164 #include "mdaassistants.h"
165 #include "eemessagebox.h"
166 #include "finalizerthread.h"
167 #include "threadsuspend.h"
168 #include "disassembler.h"
172 #include "dwreport.h"
173 #endif // !FEATURE_PAL
175 #include "stringarraylist.h"
176 #include "stubhelpers.h"
178 #ifdef FEATURE_STACK_SAMPLING
179 #include "stacksampler.h"
187 #ifdef FEATURE_COMINTEROP
188 #include "runtimecallablewrapper.h"
189 #include "notifyexternals.h"
190 #include "mngstdinterfaces.h"
191 #include "rcwwalker.h"
192 #endif // FEATURE_COMINTEROP
194 #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
195 #include "olecontexthelpers.h"
196 #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
198 #ifdef PROFILING_SUPPORTED
199 #include "proftoeeinterfaceimpl.h"
200 #include "profilinghelper.h"
201 #endif // PROFILING_SUPPORTED
203 #ifdef FEATURE_COMINTEROP
204 #include "synchronizationcontextnative.h" // For SynchronizationContextNative::Cleanup
207 #ifdef FEATURE_INTERPRETER
208 #include "interpreter.h"
209 #endif // FEATURE_INTERPRETER
211 #include "../binder/inc/coreclrbindercommon.h"
214 #ifdef FEATURE_PERFMAP
218 #include "eventpipe.h"
221 // Included for referencing __security_cookie
223 #endif // !FEATURE_PAL
225 #ifdef FEATURE_GDBJIT
227 #endif // FEATURE_GDBJIT
229 #ifndef CROSSGEN_COMPILE
230 static int GetThreadUICultureId(__out LocaleIDValue* pLocale); // TODO: This shouldn't use the LCID. We should rely on name instead
232 static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames);
233 #endif // !CROSSGEN_COMPILE
235 HRESULT EEStartup(COINITIEE fFlags);
238 #ifndef CROSSGEN_COMPILE
239 static void InitializeGarbageCollector();
241 #ifdef DEBUGGING_SUPPORTED
242 static void InitializeDebugger(void);
243 static void TerminateDebugger(void);
244 extern "C" HRESULT __cdecl CorDBGetInterface(DebugInterface** rcInterface);
245 #endif // DEBUGGING_SUPPORTED
246 #endif // !CROSSGEN_COMPILE
251 // Remember how the last startup of EE went.
252 HRESULT g_EEStartupStatus = S_OK;
254 // Flag indicating if the EE has been started. This is set prior to initializing the default AppDomain, and so does not indicate that
255 // the EE is fully able to execute arbitrary managed code. To ensure the EE is fully started, call EnsureEEStarted rather than just
256 // checking this flag.
257 Volatile<BOOL> g_fEEStarted = FALSE;
259 // Flag indicating if the EE should be suspended on shutdown.
260 BOOL g_fSuspendOnShutdown = FALSE;
262 // Flag indicating if the finalizer thread should be suspended on shutdown.
263 BOOL g_fSuspendFinalizerOnShutdown = FALSE;
265 // Flag indicating if the EE was started up by COM.
266 extern BOOL g_fEEComActivatedStartup;
268 // flag indicating that EE was not started up by IJW, Hosted, COM or my managed exe.
269 extern BOOL g_fEEOtherStartup;
271 // The OS thread ID of the thread currently performing EE startup, or 0 if there is no such thread.
272 DWORD g_dwStartupThreadId = 0;
274 // Event to synchronize EE shutdown.
275 static CLREvent * g_pEEShutDownEvent;
277 static DangerousNonHostedSpinLock g_EEStartupLock;
279 HRESULT InitializeEE(COINITIEE flags)
282 #ifdef FEATURE_EVENT_TRACE
283 if(!g_fEEComActivatedStartup)
284 g_fEEOtherStartup = TRUE;
285 #endif // FEATURE_EVENT_TRACE
286 return EnsureEEStarted(flags);
289 // ---------------------------------------------------------------------------
290 // %%Function: EnsureEEStarted()
292 // Description: Ensure the CLR is started.
293 // ---------------------------------------------------------------------------
294 HRESULT EnsureEEStarted(COINITIEE flags)
310 // On non x86 platforms, when we load mscorlib.dll during EEStartup, we will
311 // re-enter _CorDllMain with a DLL_PROCESS_ATTACH for mscorlib.dll. We are
312 // far enough in startup that this is allowed, however we don't want to
313 // re-start the startup code so we need to check to see if startup has
314 // been initiated or completed before we call EEStartup.
316 // We do however want to make sure other threads block until the EE is started,
317 // which we will do further down.
320 BEGIN_ENTRYPOINT_NOTHROW;
322 #if defined(FEATURE_APPX) && !defined(CROSSGEN_COMPILE)
323 STARTUP_FLAGS startupFlags = CorHost2::GetStartupFlags();
324 // On CoreCLR, the host is in charge of determining whether the process is AppX or not.
325 AppX::SetIsAppXProcess(!!(startupFlags & STARTUP_APPX_APP_MODEL));
329 // The sooner we do this, the sooner we avoid probing registry entries.
330 // (Perf Optimization for VSWhidbey:113373.)
331 REGUTIL::InitOptionalConfigCache();
338 DangerousNonHostedSpinLockHolder lockHolder(&g_EEStartupLock);
340 // Now that we've acquired the lock, check again to make sure we aren't in
341 // the process of starting the CLR or that it hasn't already been fully started.
342 // At this point, if startup has been inited we don't have anything more to do.
343 // And if EEStartup already failed before, we don't do it again.
344 if (!g_fEEStarted && !g_fEEInit && SUCCEEDED (g_EEStartupStatus))
346 g_dwStartupThreadId = GetCurrentThreadId();
349 bStarted=g_fEEStarted;
350 hr = g_EEStartupStatus;
352 g_dwStartupThreadId = 0;
356 hr = g_EEStartupStatus;
357 if (SUCCEEDED(g_EEStartupStatus))
364 #ifdef FEATURE_TESTHOOKS
366 TESTHOOKCALL(RuntimeStarted(RTS_INITIALIZED));
368 END_ENTRYPOINT_NOTHROW;
373 // g_fEEStarted is TRUE, but startup may not be complete since we initialize the default AppDomain
374 // *after* setting that flag. g_fEEStarted is set inside of g_EEStartupLock, and that lock is
375 // not released until the EE is really started - so we can quickly check whether the EE is definitely
376 // started by checking if that lock is currently held. If it is not, then we know the other thread
377 // (that is actually doing the startup) has finished startup. If it is currently held, then we
378 // need to wait for the other thread to release it, which we do by simply acquiring the lock ourselves.
380 // We do not want to do this blocking if we are the thread currently performing EE startup. So we check
383 // Note that the call to IsHeld here is an "acquire" barrier, as is acquiring the lock. And the release of
384 // the lock by the other thread is a "release" barrier, due to the volatile semantics in the lock's
385 // implementation. This assures us that once we observe the lock having been released, we are guaranteed
386 // to observe a fully-initialized EE.
388 // A note about thread affinity here: we're using the OS thread ID of the current thread without
389 // asking the host to pin us to this thread, as we did above. We can get away with this, because we are
390 // only interested in a particular thread ID (that of the "startup" thread) and *that* particular thread
391 // is already affinitized by the code above. So if we get that particular OS thread ID, we know for sure
392 // we are really the startup thread.
394 if (g_EEStartupLock.IsHeld() && g_dwStartupThreadId != GetCurrentThreadId())
396 DangerousNonHostedSpinLockHolder lockHolder(&g_EEStartupLock);
399 hr = g_EEStartupStatus;
400 if (SUCCEEDED(g_EEStartupStatus))
410 #ifndef CROSSGEN_COMPILE
413 // This is our Ctrl-C, Ctrl-Break, etc. handler.
414 static BOOL WINAPI DbgCtrlCHandler(DWORD dwCtrlType)
418 #if defined(DEBUGGING_SUPPORTED)
419 // Note that if a managed-debugger is attached, it's actually attached with the native
420 // debugging pipeline and it will get a control-c notifications via native debug events.
421 // However, if we let the native debugging pipeline handle the event and send the notification
422 // to the debugger, then we break pre-V4 behaviour because we intercept handlers registered
423 // in-process. See Dev10 Bug 846455 for more information.
424 if (CORDebuggerAttached() &&
425 (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT))
427 return g_pDebugInterface->SendCtrlCToDebugger(dwCtrlType);
430 #endif // DEBUGGING_SUPPORTED
432 if (dwCtrlType == CTRL_CLOSE_EVENT)
434 // Initiate shutdown so the ProcessExit handlers run
435 ForceEEShutdown(SCA_ReturnWhenShutdownComplete);
438 g_fInControlC = true; // only for weakening assertions in checked build.
439 return FALSE; // keep looking for a real handler.
444 // A host can specify that it only wants one version of hosting interface to be used.
445 BOOL g_singleVersionHosting;
449 void InitializeStartupFlags()
457 STARTUP_FLAGS flags = CorHost2::GetStartupFlags();
460 if (flags & STARTUP_CONCURRENT_GC)
466 g_heap_type = (flags & STARTUP_SERVER_GC) == 0 ? GC_HEAP_WKS : GC_HEAP_SVR;
467 g_IGCHoardVM = (flags & STARTUP_HOARD_GC_VM) == 0 ? 0 : 1;
469 #endif // CROSSGEN_COMPILE
472 #ifdef FEATURE_PREJIT
473 // BBSweepStartFunction is the first function to execute in the BBT sweeper thread.
474 // It calls WatchForSweepEvent where we wait until a sweep occurs.
475 DWORD __stdcall BBSweepStartFunction(LPVOID lpArgs)
485 class CLRBBSweepCallback : public ICLRBBSweepCallback
487 virtual HRESULT WriteProfileData()
489 BEGIN_ENTRYPOINT_NOTHROW
491 Module::WriteAllModuleProfileData(false);
492 END_ENTRYPOINT_NOTHROW;
499 g_BBSweep.WatchForSweepEvents(&clrCallback);
504 EX_END_CATCH(RethrowTerminalExceptions)
508 #endif // FEATURE_PREJIT
511 //-----------------------------------------------------------------------------
523 GSCookie * pGSCookiePtr = GetProcessGSCookiePtr();
526 if(!ClrVirtualProtect((LPVOID)pGSCookiePtr, sizeof(GSCookie), PAGE_EXECUTE_READWRITE, &oldProtection))
532 // The GSCookie cannot be in a writeable page
533 assert(((oldProtection & (PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|
534 PAGE_EXECUTE_WRITECOPY|PAGE_WRITECOMBINE)) == 0));
536 // Forces VC cookie to be initialized.
537 void * pf = &__security_check_cookie;
540 GSCookie val = (GSCookie)(__security_cookie ^ GetTickCount());
541 #else // !FEATURE_PAL
542 // REVIEW: Need something better for PAL...
543 GSCookie val = (GSCookie)GetTickCount();
544 #endif // !FEATURE_PAL
547 // In _DEBUG, always use the same value to make it easier to search for the cookie
548 val = (GSCookie) WIN64_ONLY(0x9ABCDEF012345678) NOT_WIN64(0x12345678);
551 // To test if it is initialized. Also for ICorMethodInfo::getGSCookie()
556 if(!ClrVirtualProtect((LPVOID)pGSCookiePtr, sizeof(GSCookie), oldProtection, &oldProtection))
562 Volatile<BOOL> g_bIsGarbageCollectorFullyInitialized = FALSE;
564 void SetGarbageCollectorFullyInitialized()
566 LIMITED_METHOD_CONTRACT;
568 g_bIsGarbageCollectorFullyInitialized = TRUE;
571 // Tells whether the garbage collector is fully initialized
572 // Stronger than IsGCHeapInitialized
573 BOOL IsGarbageCollectorFullyInitialized()
575 LIMITED_METHOD_CONTRACT;
577 return g_bIsGarbageCollectorFullyInitialized;
580 // ---------------------------------------------------------------------------
581 // %%Function: EEStartupHelper
584 // fFlags - Initialization flags for the engine. See the
585 // EEStartupFlags enumerator for valid values.
591 // Reserved to initialize the EE runtime engine explicitly.
592 // ---------------------------------------------------------------------------
594 #ifndef IfFailGotoLog
595 #define IfFailGotoLog(EXPR, LABEL) \
599 STRESS_LOG2(LF_STARTUP, LL_ALWAYS, "%s failed with code %x", #EXPR, hr);\
603 STRESS_LOG1(LF_STARTUP, LL_ALWAYS, "%s completed", #EXPR);\
608 #define IfFailGoLog(EXPR) IfFailGotoLog(EXPR, ErrExit)
611 void EEStartupHelper(COINITIEE fFlags)
620 #ifdef ENABLE_CONTRACTS_IMPL
622 extern void ContractRegressionCheck();
623 ContractRegressionCheck();
628 static ConfigDWORD breakOnEELoad;
633 #ifndef CROSSGEN_COMPILE
636 ::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);
639 #endif // CROSSGEN_COMPILE
641 // SString initialization
642 // This needs to be done before config because config uses SString::Empty()
645 // Initialize EEConfig
648 IfFailGo(EEConfig::Setup());
651 #ifndef CROSSGEN_COMPILE
652 // Initialize Numa and CPU group information
653 // Need to do this as early as possible. Used by creating object handle
654 // table inside Ref_Initialization() before GC is initialized.
655 NumaNodeInfo::InitNumaNodeInfo();
656 CPUGroupInfo::EnsureInitialized();
659 // Initialize global configuration settings based on startup flags
660 // This needs to be done before the EE has started
661 InitializeStartupFlags();
663 MethodDescBackpatchInfoTracker::StaticInitialize();
666 STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "Returned successfully from InitThreadManager");
668 #ifdef FEATURE_PERFTRACING
669 // Initialize the event pipe.
670 EventPipe::Initialize();
671 #endif // FEATURE_PERFTRACING
673 #ifdef FEATURE_GDBJIT
675 NotifyGdb::Initialize();
676 #endif // FEATURE_GDBJIT
678 #ifdef FEATURE_EVENT_TRACE
679 // Initialize event tracing early so we can trace CLR startup time events.
680 InitializeEventTracing();
682 // Fire the EE startup ETW event
683 ETWFireEvent(EEStartupStart_V1);
684 #endif // FEATURE_EVENT_TRACE
690 #ifdef FEATURE_TESTHOOKS
691 IfFailGo(CLRTestHookManager::CheckConfig());
694 #endif // CROSSGEN_COMPILE
698 if (REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_StressLog, g_pConfig->StressLog ()) != 0) {
699 unsigned facilities = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_LogFacility, LF_ALL);
700 unsigned level = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::EXTERNAL_LogLevel, LL_INFO1000);
701 unsigned bytesPerThread = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_StressLogSize, STRESSLOG_CHUNK_SIZE * 4);
702 unsigned totalBytes = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_TotalStressLogSize, STRESSLOG_CHUNK_SIZE * 1024);
703 StressLog::Initialize(facilities, level, bytesPerThread, totalBytes, GetModuleInst());
704 g_pStressLog = &StressLog::theLog;
712 #ifdef ENABLE_PERF_LOG
713 PerfLog::PerfLogInitialize();
714 #endif //ENABLE_PERF_LOG
716 #ifdef FEATURE_PERFMAP
717 PerfMap::Initialize();
720 STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "===================EEStartup Starting===================");
722 #ifndef CROSSGEN_COMPILE
724 IfFailGoLog(EnsureRtlFunctions());
725 #endif // !FEATURE_PAL
730 // Initialize the general Assembly Binder infrastructure
731 IfFailGoLog(CCoreCLRBinderHelper::Init());
733 if (g_pConfig != NULL)
735 IfFailGoLog(g_pConfig->sync());
738 // Fire the runtime information ETW event
739 ETW::InfoLog::RuntimeInformation(ETW::InfoLog::InfoStructs::Normal);
741 if (breakOnEELoad.val(CLRConfig::UNSUPPORTED_BreakOnEELoad) == 1)
744 _ASSERTE(!"Start loading EE!");
750 #ifdef ENABLE_STARTUP_DELAY
751 PREFIX_ASSUME(NULL != g_pConfig);
752 if (g_pConfig->StartupDelayMS())
754 ClrSleepEx(g_pConfig->StartupDelayMS(), FALSE);
759 if ((g_pConfig->GetGCStressLevel() & (EEConfig::GCSTRESS_INSTR_JIT | EEConfig::GCSTRESS_INSTR_NGEN)) != 0)
761 Disassembler::StaticInitialize();
762 if (!Disassembler::IsAvailable())
764 fprintf(stderr, "External disassembler is not available.\n");
768 #endif // USE_DISASSEMBLER
770 // Monitors, Crsts, and SimpleRWLocks all use the same spin heuristics
771 // Cache the (potentially user-overridden) values now so they are accessible from asm routines
772 InitializeSpinConstants();
774 #ifndef CROSSGEN_COMPILE
777 #ifdef FEATURE_PREJIT
778 // Initialize the sweeper thread.
779 if (g_pConfig->GetZapBBInstr() != NULL)
782 HANDLE hBBSweepThread = ::CreateThread(NULL,
784 (LPTHREAD_START_ROUTINE) BBSweepStartFunction,
788 _ASSERTE(hBBSweepThread);
789 g_BBSweep.SetBBSweepThreadHandle(hBBSweepThread);
791 #endif // FEATURE_PREJIT
793 #ifdef FEATURE_INTERPRETER
794 Interpreter::Initialize();
795 #endif // FEATURE_INTERPRETER
797 StubManager::InitializeStubManagers();
801 // Record mscorwks geometry
802 PEDecoder pe(g_pMSCorEE);
804 g_runtimeLoadedBaseAddress = (SIZE_T)pe.GetBase();
805 g_runtimeVirtualSize = (SIZE_T)pe.GetVirtualSize();
806 InitCodeAllocHint(g_runtimeLoadedBaseAddress, g_runtimeVirtualSize, GetRandomInt(64));
808 #endif // !FEATURE_PAL
810 #endif // CROSSGEN_COMPILE
812 // Set up the cor handle map. This map is used to load assemblies in
813 // memory instead of using the normal system load
816 AccessCheckOptions::Startup();
818 MscorlibBinder::Startup();
821 StubLinkerCPU::Init();
823 #ifndef CROSSGEN_COMPILE
825 InitializeGarbageCollector();
827 // Initialize remoting
829 if (!GCHandleUtilities::GetGCHandleManager()->Initialize())
831 IfFailGo(E_OUTOFMEMORY);
834 g_pEEShutDownEvent = new CLREvent();
835 g_pEEShutDownEvent->CreateManualEvent(FALSE);
837 VirtualCallStubManager::InitStatic();
839 GCInterface::m_MemoryPressureLock.Init(CrstGCMemoryPressure);
841 #endif // CROSSGEN_COMPILE
843 // Setup the domains. Threads are started in a default domain.
845 // Static initialization
846 PEAssembly::Attach();
847 BaseDomain::Attach();
848 SystemDomain::Attach();
850 // Start up the EE intializing all the global variables
855 ExecutionManager::Init();
859 #ifndef CROSSGEN_COMPILE
862 if (!RegisterOutOfProcessWatsonCallbacks())
866 #endif // !FEATURE_PAL
868 #ifdef DEBUGGING_SUPPORTED
871 // Initialize the debugging services. This must be done before any
872 // EE thread objects are created, and before any classes or
873 // modules are loaded.
874 InitializeDebugger(); // throws on error
876 #endif // DEBUGGING_SUPPORTED
879 ManagedDebuggingAssistants::EEStartupActivation();
882 #ifdef PROFILING_SUPPORTED
883 // Initialize the profiling services.
884 hr = ProfilingAPIUtility::InitializeProfiling();
886 _ASSERTE(SUCCEEDED(hr));
888 #endif // PROFILING_SUPPORTED
890 InitializeExceptionHandling();
893 // Install our global exception filter
895 if (!InstallUnhandledExceptionFilter())
903 #ifdef DEBUGGING_SUPPORTED
904 // Notify debugger once the first thread is created to finish initialization.
905 if (g_pDebugInterface != NULL)
907 g_pDebugInterface->StartupPhase2(GetThread());
911 InitPreStubManager();
913 #ifdef FEATURE_COMINTEROP
914 InitializeComInterop();
915 #endif // FEATURE_COMINTEROP
920 // Before setting up the execution manager initialize the first part
921 // of the JIT helpers.
925 SyncBlockCache::Attach();
927 // Set up the sync block
928 SyncBlockCache::Start();
930 StackwalkCache::Init();
932 // This isn't done as part of InitializeGarbageCollector() above because it
933 // requires write barriers to have been set up on x86, which happens as part
934 // of InitJITHelpers1.
935 hr = g_pGCHeap->Initialize();
938 // This isn't done as part of InitializeGarbageCollector() above because thread
939 // creation requires AppDomains to have been set up.
940 FinalizerThread::FinalizerThreadCreate();
942 // Now we really have fully initialized the garbage collector
943 SetGarbageCollectorFullyInitialized();
945 #ifdef DEBUGGING_SUPPORTED
946 // Make a call to publish the DefaultDomain for the debugger
947 // This should be done before assemblies/modules are loaded into it (i.e. SystemDomain::Init)
948 // and after its OK to switch GC modes and syncronize for sending events to the debugger.
949 // @dbgtodo synchronization: this can probably be simplified in V3
950 LOG((LF_CORDB | LF_SYNC | LF_STARTUP, LL_INFO1000, "EEStartup: adding default domain 0x%x\n",
951 SystemDomain::System()->DefaultDomain()));
952 SystemDomain::System()->PublishAppDomainAndInformDebugger(SystemDomain::System()->DefaultDomain());
955 #endif // CROSSGEN_COMPILE
957 SystemDomain::System()->Init();
959 #ifdef PROFILING_SUPPORTED
960 // <TODO>This is to compensate for the DefaultDomain workaround contained in
961 // SystemDomain::Attach in which the first user domain is created before profiling
962 // services can be initialized. Profiling services cannot be moved to before the
963 // workaround because it needs SetupThread to be called.</TODO>
965 SystemDomain::NotifyProfilerStartup();
966 #endif // PROFILING_SUPPORTED
970 SystemDomain::System()->DefaultDomain()->LoadSystemAssemblies();
972 SystemDomain::System()->DefaultDomain()->SetupSharedStatics();
975 APIThreadStress::SetThreadStressCount(g_pConfig->GetAPIThreadStressCount());
977 #ifdef FEATURE_STACK_SAMPLING
978 StackSampler::Init();
981 #ifndef CROSSGEN_COMPILE
982 if (!NingenEnabled())
984 // Perform any once-only SafeHandle initialization.
988 #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
989 // retrieve configured max size for the mini-metadata buffer (defaults to 64KB)
990 g_MiniMetaDataBuffMaxSize = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MiniMdBufferCapacity);
991 // align up to GetOsPageSize(), with a maximum of 1 MB
992 g_MiniMetaDataBuffMaxSize = (DWORD) min(ALIGN_UP(g_MiniMetaDataBuffMaxSize, GetOsPageSize()), 1024 * 1024);
993 // allocate the buffer. this is never touched while the process is running, so it doesn't
994 // contribute to the process' working set. it is needed only as a "shadow" for a mini-metadata
995 // buffer that will be set up and reported / updated in the Watson process (the
996 // DacStreamsManager class coordinates this)
997 g_MiniMetaDataBuffAddress = (TADDR) ClrVirtualAlloc(NULL,
998 g_MiniMetaDataBuffMaxSize, MEM_COMMIT, PAGE_READWRITE);
999 #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
1001 #endif // CROSSGEN_COMPILE
1003 g_fEEStarted = TRUE;
1004 g_EEStartupStatus = S_OK;
1006 STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "===================EEStartup Completed===================");
1008 #ifndef CROSSGEN_COMPILE
1012 //if g_fEEStarted was false when we loaded the System Module, we did not run ExpandAll on it. In
1013 //this case, make sure we run ExpandAll here. The rationale is that if we Jit before g_fEEStarted
1014 //is true, we can't initialize Com, so we can't jit anything that uses Com types. Also, it's
1015 //probably not safe to Jit while g_fEEStarted is false.
1017 //Also, if you run this it's possible we'll call CoInitialize, which defaults to MTA. This might
1018 //mess up an application that uses STA. However, this mode is only supported for certain limited
1019 //jit testing scenarios, so it can live with the limitation.
1020 if (g_pConfig->ExpandModulesOnLoad())
1022 SystemDomain::SystemModule()->ExpandAll();
1025 // Perform mscorlib consistency check if requested
1026 g_Mscorlib.CheckExtended();
1034 #endif // !CROSSGEN_COMPILE
1040 #ifdef CROSSGEN_COMPILE
1041 // for minimal impact we won't update hr for regular builds
1042 hr = GET_EXCEPTION()->GetHR();
1043 _ASSERTE(FAILED(hr));
1044 StackSString exceptionMessage;
1045 GET_EXCEPTION()->GetMessage(exceptionMessage);
1046 fprintf(stderr, "%S\n", exceptionMessage.GetUnicode());
1047 #endif // CROSSGEN_COMPILE
1049 EX_END_CATCH(RethrowTerminalExceptionsWithInitCheck)
1051 if (!g_fEEStarted) {
1058 g_EEStartupStatus = hr;
1061 if (breakOnEELoad.val(CLRConfig::UNSUPPORTED_BreakOnEELoad) == 2)
1064 _ASSERTE(!"Done loading EE!");
1072 LONG FilterStartupException(PEXCEPTION_POINTERS p, PVOID pv)
1079 PRECONDITION(CheckPointer(p));
1080 PRECONDITION(CheckPointer(pv));
1083 g_EEStartupStatus = (HRESULT)p->ExceptionRecord->ExceptionInformation[0];
1085 // Make sure we got a failure code in this case
1086 if (!FAILED(g_EEStartupStatus))
1087 g_EEStartupStatus = E_FAIL;
1089 // Initializations has failed so reset the g_fEEInit flag.
1092 if (p->ExceptionRecord->ExceptionCode == BOOTUP_EXCEPTION_COMPLUS)
1094 // Don't ever handle the exception in a checked build
1096 return EXCEPTION_EXECUTE_HANDLER;
1100 return EXCEPTION_CONTINUE_SEARCH;
1103 // EEStartup is responcible for all the one time intialization of the runtime. Some of the highlights of
1104 // what it does include
1105 // * Creates the default and shared, appdomains.
1106 // * Loads mscorlib.dll and loads up the fundamental types (System.Object ...)
1108 // see code:EEStartup#TableOfContents for more on the runtime in general.
1109 // see code:#EEShutdown for a analagous routine run during shutdown.
1111 HRESULT EEStartup(COINITIEE fFlags)
1113 // Cannot use normal contracts here because of the PAL_TRY.
1114 STATIC_CONTRACT_NOTHROW;
1116 _ASSERTE(!g_fEEStarted && !g_fEEInit && SUCCEEDED (g_EEStartupStatus));
1118 PAL_TRY(COINITIEE *, pfFlags, &fFlags)
1120 #ifndef CROSSGEN_COMPILE
1121 InitializeClrNotifications();
1123 InitializeJITNotificationTable();
1124 DacGlobals::Initialize();
1126 #endif // CROSSGEN_COMPILE
1128 EEStartupHelper(*pfFlags);
1130 PAL_EXCEPT_FILTER (FilterStartupException)
1132 // The filter should have set g_EEStartupStatus to a failure HRESULT.
1133 _ASSERTE(FAILED(g_EEStartupStatus));
1137 return g_EEStartupStatus;
1141 #ifndef CROSSGEN_COMPILE
1143 #ifdef FEATURE_COMINTEROP
1145 void InnerCoEEShutDownCOM()
1154 static LONG AlreadyDone = -1;
1156 if (g_fEEStarted != TRUE)
1159 if (FastInterlockIncrement(&AlreadyDone) != 0)
1162 g_fShutDownCOM = true;
1164 // Release IJupiterGCMgr *
1165 RCWWalker::OnEEShutdown();
1167 // Release all of the RCWs in all contexts in all caches.
1168 ReleaseRCWsInCaches(NULL);
1171 // Cleanup cached factory pointer in SynchronizationContextNative
1172 SynchronizationContextNative::Cleanup();
1176 // ---------------------------------------------------------------------------
1177 // %%Function: CoEEShutdownCOM()
1186 // COM Objects shutdown stuff should be done here
1187 // ---------------------------------------------------------------------------
1188 void STDMETHODCALLTYPE CoEEShutDownCOM()
1199 if (g_fEEStarted != TRUE)
1203 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1205 InnerCoEEShutDownCOM();
1207 END_EXTERNAL_ENTRYPOINT;
1209 // API doesn't allow us to communicate a failure HRESULT. MDAs can
1210 // be enabled to catch failure inside CanRunManagedCode.
1211 // _ASSERTE(SUCCEEDED(hr));
1214 #endif // FEATURE_COMINTEROP
1216 // ---------------------------------------------------------------------------
1217 // %%Function: ForceEEShutdown()
1219 // Description: Force the EE to shutdown now.
1221 // Note: returns when sca is SCA_ReturnWhenShutdownComplete.
1222 // ---------------------------------------------------------------------------
1223 void ForceEEShutdown(ShutdownCompleteAction sca)
1225 WRAPPER_NO_CONTRACT;
1227 // Don't bother to take the lock for this case.
1229 STRESS_LOG0(LF_STARTUP, INFO3, "EEShutdown invoked from ForceEEShutdown");
1230 EEPolicy::HandleExitProcess(sca);
1233 //---------------------------------------------------------------------------
1234 // %%Function: ExternalShutdownHelper
1237 // int exitCode :: process exit code
1238 // ShutdownCompleteAction sca :: indicates whether ::ExitProcess() is
1239 // called or if the function returns.
1245 // This is a helper shared by CorExitProcess and ShutdownRuntimeWithoutExiting
1246 // which causes the runtime to shutdown after the appropriate checks.
1247 // ---------------------------------------------------------------------------
1248 static void ExternalShutdownHelper(int exitCode, ShutdownCompleteAction sca)
1257 CONTRACT_VIOLATION(GCViolation | ModeViolation);
1259 if (g_fEEShutDown || !g_fEEStarted)
1262 if (HasIllegalReentrancy())
1267 if (!CanRunManagedCode())
1272 // The exit code for the process is communicated in one of two ways. If the
1273 // entrypoint returns an 'int' we take that. Otherwise we take a latched
1274 // process exit code. This can be modified by the app via System.SetExitCode().
1275 SetLatchedExitCode(exitCode);
1278 ForceEEShutdown(sca);
1280 // @TODO: If we cannot run ManagedCode, BEGIN_EXTERNAL_ENTRYPOINT will skip
1281 // the shutdown. We could call ::ExitProcess in that failure case, but that
1282 // would violate our hosting agreement. We are supposed to go through EEPolicy::
1283 // HandleExitProcess(). Is this legal if !CanRunManagedCode()?
1287 //---------------------------------------------------------------------------
1288 // %%Function: void STDMETHODCALLTYPE CorExitProcess(int exitCode)
1291 // int exitCode :: process exit code
1297 // COM Objects shutdown stuff should be done here
1298 // ---------------------------------------------------------------------------
1299 extern "C" void STDMETHODCALLTYPE CorExitProcess(int exitCode)
1301 WRAPPER_NO_CONTRACT;
1303 ExternalShutdownHelper(exitCode, SCA_ExitProcessWhenShutdownComplete);
1306 //---------------------------------------------------------------------------
1307 // %%Function: ShutdownRuntimeWithoutExiting
1310 // int exitCode :: process exit code
1316 // This is a helper used only by the v4+ Shim to shutdown this runtime and
1317 // and return when the work has completed. It is exposed to the Shim via
1319 // ---------------------------------------------------------------------------
1320 void ShutdownRuntimeWithoutExiting(int exitCode)
1322 WRAPPER_NO_CONTRACT;
1324 ExternalShutdownHelper(exitCode, SCA_ReturnWhenShutdownComplete);
1327 //---------------------------------------------------------------------------
1328 // %%Function: IsRuntimeStarted
1331 // pdwStartupFlags: out parameter that is set to the startup flags if the
1332 // runtime is started.
1335 // TRUE if the runtime has been started, FALSE otherwise.
1338 // This is a helper used only by the v4+ Shim to determine if this runtime
1339 // has ever been started. It is exposed ot the Shim via GetCLRFunction.
1340 // ---------------------------------------------------------------------------
1341 BOOL IsRuntimeStarted(DWORD *pdwStartupFlags)
1343 LIMITED_METHOD_CONTRACT;
1345 if (pdwStartupFlags != NULL) // this parameter is optional
1347 *pdwStartupFlags = 0;
1349 return g_fEEStarted;
1352 static bool WaitForEndOfShutdown_OneIteration()
1360 // We are shutting down. GC triggers does not have any effect now.
1361 CONTRACT_VIOLATION(GCViolation);
1363 // If someone calls EEShutDown while holding OS loader lock, the thread we created for shutdown
1364 // won't start running. This is a deadlock we can not fix. Instead, we timeout and continue the
1366 DWORD timeout = GetEEPolicy()->GetTimeout(OPR_ProcessExit);
1368 ULONGLONG endTime = CLRGetTickCount64() + timeout;
1373 ULONGLONG curTime = CLRGetTickCount64();
1374 if (curTime > endTime)
1380 #ifdef PROFILING_SUPPORTED
1381 if (CORProfilerPresent())
1383 // A profiler is loaded, so just wait without timeout. This allows
1384 // profilers to complete potentially lengthy post processing, without the
1385 // CLR killing them off first. The Office team's server memory profiler,
1386 // for example, does a lot of post-processing that can exceed the 80
1387 // second imit we normally impose here. The risk of waiting without
1388 // timeout is that, if there really is a deadlock, shutdown will hang.
1389 // Since that will only happen if a profiler is loaded, that is a
1390 // reasonable compromise
1394 #endif //PROFILING_SUPPORTED
1396 timeout = static_cast<DWORD>(endTime - curTime);
1398 DWORD status = g_pEEShutDownEvent->Wait(timeout,TRUE);
1399 if (status == WAIT_OBJECT_0 || status == WAIT_TIMEOUT)
1412 EX_END_CATCH(SwallowAllExceptions);
1416 void WaitForEndOfShutdown()
1424 // We are shutting down. GC triggers does not have any effect now.
1425 CONTRACT_VIOLATION(GCViolation);
1427 Thread *pThread = GetThread();
1428 // After a thread is blocked in WaitForEndOfShutdown, the thread should not enter runtime again,
1429 // and block at WaitForEndOfShutdown again.
1432 _ASSERTE(!pThread->HasThreadStateNC(Thread::TSNC_BlockedForShutdown));
1433 pThread->SetThreadStateNC(Thread::TSNC_BlockedForShutdown);
1436 while (!WaitForEndOfShutdown_OneIteration());
1439 // ---------------------------------------------------------------------------
1440 // Function: EEShutDownHelper(BOOL fIsDllUnloading)
1442 // The real meat of shut down happens here. See code:#EEShutDown for details, including
1443 // what fIsDllUnloading means.
1445 void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading)
1454 // Used later for a callback.
1459 ETW::EnumerationLog::ProcessShutdown();
1462 #ifdef FEATURE_PERFTRACING
1463 // Shutdown the event pipe.
1464 EventPipe::Shutdown();
1465 #endif // FEATURE_PERFTRACING
1467 #if defined(FEATURE_COMINTEROP)
1468 // Get the current thread.
1469 Thread * pThisThread = GetThread();
1472 // If the process is detaching then set the global state.
1473 // This is used to get around FreeLibrary problems.
1475 g_fProcessDetach = true;
1477 if (IsDbgHelperSpecialThread())
1479 // Our debugger helper thread does not allow Thread object to be set up.
1480 // We should not run shutdown code on debugger helper thread.
1481 _ASSERTE(fIsDllUnloading);
1486 // stop API thread stress
1487 APIThreadStress::SetThreadStressCount(0);
1490 STRESS_LOG1(LF_STARTUP, LL_INFO10, "EEShutDown entered unloading = %d", fIsDllUnloading);
1494 _ASSERTE(!"An assert was hit before EE Shutting down");
1496 if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_BreakOnEEShutdown))
1497 _ASSERTE(!"Shutting down EE!");
1500 #ifdef DEBUGGING_SUPPORTED
1501 // This is a nasty, terrible, horrible thing. If we're being
1502 // called from our DLL main, then the odds are good that our DLL
1503 // main has been called as the result of some person calling
1504 // ExitProcess. That rips the debugger helper thread away very
1505 // ungracefully. This check is an attempt to recognize that case
1506 // and avoid the impending hang when attempting to get the helper
1507 // thread to do things for us.
1508 if ((g_pDebugInterface != NULL) && g_fProcessDetach)
1509 g_pDebugInterface->EarlyHelperThreadDeath();
1510 #endif // DEBUGGING_SUPPORTED
1512 BOOL fFinalizeOK = FALSE;
1516 ClrFlsSetThreadType(ThreadType_Shutdown);
1518 if (fIsDllUnloading && g_fEEShutDown)
1520 // I'm in the final shutdown and the first part has already been run.
1524 // Indicate the EE is the shut down phase.
1525 g_fEEShutDown |= ShutDown_Start;
1529 // Terminate the BBSweep thread
1530 g_BBSweep.ShutdownBBSweepThread();
1532 // We perform the final GC only if the user has requested it through the GC class.
1533 // We should never do the final GC for a process detach
1534 if (!g_fProcessDetach && !g_fFastExitProcess)
1536 g_fEEShutDown |= ShutDown_Finalize1;
1537 FinalizerThread::EnableFinalization();
1538 fFinalizeOK = FinalizerThread::FinalizerThreadWatchDog();
1542 // Ok. Let's stop the EE.
1543 if (!g_fProcessDetach)
1545 // Convert key locks into "shutdown" mode. A lock in shutdown mode means:
1546 // - Only the finalizer/helper/shutdown threads will be able to take the the lock.
1547 // - Any other thread that tries takes it will just get redirected to an endless WaitForEndOfShutdown().
1549 // The only managed code that should run after this point is the finalizers for shutdown.
1550 // We convert locks needed for running + debugging such finalizers. Since such locks may need to be
1551 // juggled between multiple threads (finalizer/helper/shutdown), no single thread can take the
1552 // lock and not give it up.
1554 // Each lock needs its own shutdown flag (they can't all be converted at once).
1555 // To avoid deadlocks, we need to convert locks in order of crst level (biggest first).
1557 // Notify the debugger that we're going into shutdown to convert debugger-lock to shutdown.
1558 if (g_pDebugInterface != NULL)
1560 g_pDebugInterface->LockDebuggerForShutdown();
1563 // This call will convert the ThreadStoreLock into "shutdown" mode, just like the debugger lock above.
1564 g_fEEShutDown |= ShutDown_Finalize2;
1567 fFinalizeOK = FinalizerThread::FinalizerThreadWatchDog();
1572 // One of the calls to FinalizerThreadWatchDog failed due to timeout, so we need to prevent
1573 // any thread from running managed code, including the finalizer.
1574 ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_SHUTDOWN);
1575 g_fSuspendOnShutdown = TRUE;
1576 g_fSuspendFinalizerOnShutdown = TRUE;
1577 ThreadStore::TrapReturningThreads(TRUE);
1578 ThreadSuspend::RestartEE(FALSE, TRUE);
1582 #ifdef FEATURE_EVENT_TRACE
1583 // Flush managed object allocation logging data.
1584 // We do this after finalization is complete and returning threads have been trapped, so that
1585 // no there will be no more managed allocations and no more GCs which will manipulate the
1586 // allocation sampling data structures.
1587 ETW::TypeSystemLog::FlushObjectAllocationEvents();
1588 #endif // FEATURE_EVENT_TRACE
1590 #ifdef FEATURE_PERFMAP
1591 // Flush and close the perf map file.
1595 #ifdef FEATURE_PREJIT
1597 // If we're doing basic block profiling, we need to write the log files to disk.
1599 static BOOL fIBCLoggingDone = FALSE;
1600 if (!fIBCLoggingDone)
1602 if (g_IBCLogger.InstrEnabled())
1604 Thread * pThread = GetThread();
1605 ThreadLocalIBCInfo* pInfo = pThread->GetIBCInfo();
1607 // Acquire the Crst lock before creating the IBCLoggingDisabler object.
1608 // Only one thread at a time can be processing an IBC logging event.
1609 CrstHolder lock(IBCLogger::GetSync());
1611 IBCLoggingDisabler disableLogging( pInfo ); // runs IBCLoggingDisabler::DisableLogging
1613 CONTRACT_VIOLATION(GCViolation);
1614 Module::WriteAllModuleProfileData(true);
1617 fIBCLoggingDone = TRUE;
1621 #endif // FEATURE_PREJIT
1623 ceeInf.JitProcessShutdownWork(); // Do anything JIT-related that needs to happen at shutdown.
1625 #ifdef FEATURE_INTERPRETER
1626 // This will check a flag and do nothing if not enabled.
1627 Interpreter::PrintPostMortemData();
1628 #endif // FEATURE_INTERPRETER
1630 FastInterlockExchange((LONG*)&g_fForbidEnterEE, TRUE);
1632 if (g_fProcessDetach)
1634 ThreadStore::TrapReturningThreads(TRUE);
1637 if (!g_fProcessDetach && !fFinalizeOK)
1642 #ifdef PROFILING_SUPPORTED
1643 // If profiling is enabled, then notify of shutdown first so that the
1644 // profiler can make any last calls it needs to. Do this only if we
1645 // are not detaching
1647 if (CORProfilerPresent())
1649 // If EEShutdown is not being called due to a ProcessDetach event, so
1650 // the profiler should still be present
1651 if (!g_fProcessDetach)
1653 BEGIN_PIN_PROFILER(CORProfilerPresent());
1655 g_profControlBlock.pProfInterface->Shutdown();
1659 g_fEEShutDown |= ShutDown_Profiler;
1661 // Free the interface objects.
1662 ProfilingAPIUtility::TerminateProfiling();
1664 #endif // PROFILING_SUPPORTED
1668 g_fEEShutDown |= ShutDown_SyncBlock;
1671 // From here on out we might call stuff that violates mode requirements, but we ignore these
1672 // because we are shutting down.
1673 CONTRACT_VIOLATION(ModeViolation);
1675 #ifdef FEATURE_COMINTEROP
1676 // We need to call CoUninitialize in part one to ensure orderly shutdown of COM dlls.
1677 if (!g_fFastExitProcess)
1679 if (pThisThread!= NULL)
1681 pThisThread->CoUninitialize();
1684 #endif // FEATURE_COMINTEROP
1687 // This is the end of Part 1.
1690 // If process shutdown is in progress and Crst locks to be used in shutdown phase 2
1691 // are already in use, then skip phase 2. This will happen only when those locks
1692 // are orphaned. In Vista, the penalty for attempting to enter such locks is
1693 // instant process termination.
1694 if (g_fProcessDetach)
1696 // The assert below is a bit too aggresive and has generally brought cases that have been race conditions
1697 // and not easily reproed to validate a bug. A typical race scenario is when there are two threads,
1698 // T1 and T2, with T2 having taken a lock (e.g. SystemDomain lock), the OS terminates
1699 // T2 for some reason. Later, when we enter the shutdown thread, we would assert on such
1700 // a lock leak, but there is not much we can do since the OS wont notify us prior to thread
1701 // termination. And this is not even a user bug.
1703 // Converting it to a STRESS LOG to reduce noise, yet keep things in radar if they need
1704 // to be investigated.
1705 //_ASSERTE_MSG(g_ShutdownCrstUsageCount == 0, "Some locks to be taken during shutdown may already be orphaned!");
1706 if (g_ShutdownCrstUsageCount > 0)
1708 STRESS_LOG0(LF_STARTUP, LL_INFO10, "Some locks to be taken during shutdown may already be orphaned!");
1714 CONTRACT_VIOLATION(ModeViolation);
1716 // On the new plan, we only do the tear-down under the protection of the loader
1717 // lock -- after the OS has stopped all other threads.
1718 if (fIsDllUnloading && (g_fEEShutDown & ShutDown_Phase2) == 0)
1720 g_fEEShutDown |= ShutDown_Phase2;
1722 // Shutdown finalizer before we suspend all background threads. Otherwise we
1723 // never get to finalize anything. Obviously.
1727 _ASSERTE(!"An assert was hit After Finalizer run");
1730 // No longer process exceptions
1731 g_fNoExceptions = true;
1734 // Remove our global exception filter. If it was NULL before, we want it to be null now.
1736 UninstallUnhandledExceptionFilter();
1738 // <TODO>@TODO: This does things which shouldn't occur in part 2. Namely,
1739 // calling managed dll main callbacks (AppDomain::SignalProcessDetach), and
1740 // RemoveAppDomainFromIPC.
1742 // (If we move those things to earlier, this can be called only if fShouldWeCleanup.)</TODO>
1743 if (!g_fFastExitProcess)
1745 SystemDomain::DetachBegin();
1749 #ifdef DEBUGGING_SUPPORTED
1750 // Terminate the debugging services.
1751 TerminateDebugger();
1752 #endif // DEBUGGING_SUPPORTED
1754 StubManager::TerminateStubManagers();
1756 #ifdef FEATURE_INTERPRETER
1757 Interpreter::Terminate();
1758 #endif // FEATURE_INTERPRETER
1760 #ifdef SHOULD_WE_CLEANUP
1761 if (!g_fFastExitProcess)
1763 GCHandleUtilities::GetGCHandleManager()->Shutdown();
1765 #endif /* SHOULD_WE_CLEANUP */
1767 //@TODO: find the right place for this
1768 VirtualCallStubManager::UninitStatic();
1770 #ifdef ENABLE_PERF_LOG
1771 PerfLog::PerfLogDone();
1772 #endif //ENABLE_PERF_LOG
1776 if (!g_fFastExitProcess)
1778 SystemDomain::DetachEnd();
1781 // Unregister our vectored exception and continue handlers from the OS.
1782 // This will ensure that if any other DLL unload (after ours) has an exception,
1783 // we wont attempt to process that exception (which could lead to various
1784 // issues including AV in the runtime).
1786 // This should be done:
1788 // 1) As the last action during the shutdown so that any unexpected AVs
1789 // in the runtime during shutdown do result in FailFast in VEH.
1791 // 2) Only when the runtime is processing DLL_PROCESS_DETACH.
1792 CLRRemoveVectoredHandlers();
1794 #if USE_DISASSEMBLER
1795 Disassembler::StaticClose();
1796 #endif // USE_DISASSEMBLER
1800 _ASSERTE(!"EE Shutting down after an assert");
1805 extern unsigned FcallTimeHist[11];
1807 LOG((LF_STUBS, LL_INFO10, "FcallHist %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
1808 FcallTimeHist[0], FcallTimeHist[1], FcallTimeHist[2], FcallTimeHist[3],
1809 FcallTimeHist[4], FcallTimeHist[5], FcallTimeHist[6], FcallTimeHist[7],
1810 FcallTimeHist[8], FcallTimeHist[9], FcallTimeHist[10]));
1812 WriteJitHelperCountToSTRESSLOG();
1814 STRESS_LOG0(LF_STARTUP, LL_INFO10, "EEShutdown shutting down logging");
1816 #if 0 // Dont clean up the stress log, so that even at process exit we have a log (after all the process is going away
1817 if (!g_fFastExitProcess)
1818 StressLog::Terminate(TRUE);
1821 if (g_pConfig != NULL)
1822 g_pConfig->Cleanup();
1835 EX_END_CATCH(SwallowAllExceptions);
1837 ClrFlsClearThreadType(ThreadType_Shutdown);
1838 if (!g_fProcessDetach)
1840 g_pEEShutDownEvent->Set();
1845 #ifdef FEATURE_COMINTEROP
1847 BOOL IsThreadInSTA()
1857 // If ole32.dll is not loaded
1858 if (WszGetModuleHandle(W("ole32.dll")) == NULL)
1864 // To be conservative, check if finalizer thread is around
1867 Thread *pFinalizerThread = FinalizerThread::GetFinalizerThread();
1868 if (!pFinalizerThread || pFinalizerThread->Join(0, FALSE) != WAIT_TIMEOUT)
1876 EX_END_CATCH(SwallowAllExceptions);
1886 hr = GetCurrentThreadTypeNT5(&type);
1889 fInSTA = (type == THDTYPE_PROCESSMESSAGES) ? TRUE : FALSE;
1891 // If we get back THDTYPE_PROCESSMESSAGES, we are guaranteed to
1892 // be an STA thread. If not, we are an MTA thread, however
1893 // we can't know if the thread has been explicitly set to MTA
1894 // (via a call to CoInitializeEx) or if it has been implicitly
1895 // made MTA (if it hasn't been CoInitializeEx'd but CoInitialize
1896 // has already been called on some other thread in the process.
1900 // CoInitialize hasn't been called in the process yet so assume the current thread
1909 static LONG s_ActiveShutdownThreadCount = 0;
1911 // ---------------------------------------------------------------------------
1912 // Function: EEShutDownProcForSTAThread(LPVOID lpParameter)
1915 // LPVOID lpParameter: unused
1918 // When EEShutDown decides that the shut down logic must occur on another thread,
1919 // EEShutDown creates a new thread, and this function acts as the thread proc. See
1920 // code:#STAShutDown for details.
1922 DWORD WINAPI EEShutDownProcForSTAThread(LPVOID lpParameter)
1924 ClrFlsSetThreadType(ThreadType_ShutdownHelper);
1926 EEShutDownHelper(FALSE);
1927 for (int i = 0; i < 10; i ++)
1929 if (s_ActiveShutdownThreadCount)
1933 __SwitchToThread(20, CALLER_LIMITS_SPINNING);
1936 EPolicyAction action = GetEEPolicy()->GetDefaultAction(OPR_ProcessExit, NULL);
1937 if (action < eRudeExitProcess)
1939 action = eRudeExitProcess;
1942 UINT exitCode = GetLatchedExitCode();
1943 EEPolicy::HandleExitProcessFromEscalation(action, exitCode);
1948 // ---------------------------------------------------------------------------
1951 // Function: EEShutDown(BOOL fIsDllUnloading)
1954 // BOOL fIsDllUnloading:
1955 // * TRUE => Called from CLR's DllMain (DLL_PROCESS_DETACH). Not safe point for
1957 // * FALSE => Called some other way (e.g., end of the CLR's main). Safe to do
1962 // All ee shutdown stuff should be done here. EEShutDown is generally called in one
1964 // * 1. From code:EEPolicy::HandleExitProcess (via HandleExitProcessHelper), with
1965 // fIsDllUnloading == FALSE. This code path is typically invoked by the CLR's
1966 // main just falling through to the end. Full cleanup can be performed when
1967 // EEShutDown is called this way.
1968 // * 2. From CLR's DllMain (DLL_PROCESS_DETACH), with fIsDllUnloading == TRUE. When
1969 // called this way, much cleanup code is unsafe to run, and is thus skipped.
1971 // Actual shut down logic is factored out to EEShutDownHelper which may be called
1972 // directly by EEShutDown, or indirectly on another thread (see code:#STAShutDown).
1974 // In order that callees may also know the value of fIsDllUnloading, EEShutDownHelper
1975 // sets g_fProcessDetach = fIsDllUnloading, and g_fProcessDetach may then be retrieved
1976 // via code:IsAtProcessExit.
1978 // NOTE 1: Actually, g_fProcessDetach is set to TRUE if fIsDllUnloading is TRUE. But
1979 // g_fProcessDetach doesn't appear to be explicitly set to FALSE. (Apparently
1980 // g_fProcessDetach is implicitly initialized to FALSE as clr.dll is loaded.)
1982 // NOTE 2: EEDllMain(DLL_PROCESS_DETACH) already sets g_fProcessDetach to TRUE, so it
1983 // appears EEShutDownHelper doesn't have to.
1985 void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading)
1991 PRECONDITION(g_fEEStarted);
1994 // If we have not started runtime successfully, it is not safe to call EEShutDown.
1995 if (!g_fEEStarted || g_fFastExitProcess == 2)
2000 // We only do the first part of the shutdown once.
2001 static LONG OnlyOne = -1;
2003 if (!fIsDllUnloading)
2005 if (FastInterlockIncrement(&OnlyOne) != 0)
2007 // I'm in a regular shutdown -- but another thread got here first.
2008 // It's a race if I return from here -- I'll call ExitProcess next, and
2009 // rip things down while the first thread is half-way through a
2010 // nice cleanup. Rather than do that, I should just wait until the
2011 // first thread calls ExitProcess(). I'll die a nice death when that
2013 GCX_PREEMP_NO_DTOR();
2014 WaitForEndOfShutdown();
2018 #ifdef FEATURE_MULTICOREJIT
2019 if (!AppX::IsAppXProcess()) // When running as Appx, make the delayed timer driven writing be the only option
2021 MulticoreJitManager::StopProfileAll();
2026 #ifdef FEATURE_COMINTEROP
2027 if (!fIsDllUnloading && CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_FinalizeOnShutdown) && IsThreadInSTA())
2031 // During shutdown, we may need to release STA interface on the shutdown thread.
2032 // It is possible that the shutdown thread may deadlock. During shutdown, all
2033 // threads are blocked, except the shutdown thread and finalizer thread. If a
2034 // lock is held by one of these suspended threads, it can deadlock the process if
2035 // the shutdown thread tries to enter the lock. To mitigate this risk, create
2036 // another thread (B) to do shutdown activities (i.e., EEShutDownHelper), while
2037 // this thread (A) waits. If B deadlocks, A will time out and immediately return
2038 // from EEShutDown. A will then eventually call the OS's ExitProcess, which will
2039 // kill the deadlocked thread (and all other threads).
2041 // Many Windows Forms-based apps will also execute the code below to shift shut
2042 // down logic to a separate thread, even if they don't use COM objects. Reason
2043 // being that they will typically use a main UI thread to pump all Windows
2044 // messages (including messages that facilitate cross-thread COM calls to STA COM
2045 // objects), and will set that thread up as an STA thread just in case there are
2046 // such cross-thread COM calls to contend with. In fact, when you use VS's
2047 // File.New.Project to make a new Windows Forms project, VS will mark Main() with
2049 DWORD thread_id = 0;
2050 if (CreateThread(NULL,0,EEShutDownProcForSTAThread,NULL,0,&thread_id))
2052 GCX_PREEMP_NO_DTOR();
2054 ClrFlsSetThreadType(ThreadType_Shutdown);
2055 WaitForEndOfShutdown();
2056 FastInterlockIncrement(&s_ActiveShutdownThreadCount);
2057 ClrFlsClearThreadType(ThreadType_Shutdown);
2061 // Otherwise, this thread calls EEShutDownHelper directly. First switch to
2062 // cooperative mode if this is a managed thread
2067 EEShutDownHelper(fIsDllUnloading);
2068 if (!fIsDllUnloading)
2070 FastInterlockIncrement(&s_ActiveShutdownThreadCount);
2075 EEShutDownHelper(fIsDllUnloading);
2076 if (!fIsDllUnloading)
2078 FastInterlockIncrement(&s_ActiveShutdownThreadCount);
2083 // ---------------------------------------------------------------------------
2084 // %%Function: IsRuntimeActive()
2092 // Description: Indicates if the runtime is active or not. "Active" implies
2093 // that the runtime has started and is in a position to run
2094 // managed code. If either of these conditions are false, the
2095 // function return FALSE.
2097 // Why couldnt we add !g_fEEStarted check in CanRunManagedCode?
2100 // ExecuteDLL in ceemain.cpp could start the runtime
2101 // (due to DLL_PROCESS_ATTACH) after invoking CanRunManagedCode.
2102 // If the function were to be modified, then this scenario could fail.
2103 // Hence, I have built over CanRunManagedCode in IsRuntimeActive.
2105 // ---------------------------------------------------------------------------
2106 BOOL IsRuntimeActive()
2108 // If the runtime has started AND we can run managed code,
2109 // then runtime is considered "active".
2110 BOOL fCanRunManagedCode = CanRunManagedCode();
2111 return (g_fEEStarted && fCanRunManagedCode);
2114 // ---------------------------------------------------------------------------
2115 // %%Function: CanRunManagedCode()
2123 // Description: Indicates if one is currently allowed to run managed code.
2124 // ---------------------------------------------------------------------------
2125 NOINLINE BOOL CanRunManagedCodeRare(LoaderLockCheck::kind checkKind, HINSTANCE hInst /*= 0*/)
2129 if (checkKind == LoaderLockCheck::ForMDA) { GC_TRIGGERS; } else { GC_NOTRIGGER; }; // because of the CustomerDebugProbe
2133 // If we are shutting down the runtime, then we cannot run code.
2134 if (g_fForbidEnterEE)
2137 // If pre-loaded objects are not present, then no way.
2138 if (g_pPreallocatedOutOfMemoryException == NULL)
2141 // If we are finaling live objects or processing ExitProcess event,
2142 // we can not allow managed method to run unless the current thread
2143 // is the finalizer thread
2144 if ((g_fEEShutDown & ShutDown_Finalize2) && !FinalizerThread::IsCurrentThreadFinalizer())
2147 #if defined(FEATURE_COMINTEROP) && defined(MDA_SUPPORTED)
2148 if ((checkKind == LoaderLockCheck::ForMDA) && (NULL == MDA_GET_ASSISTANT(LoaderLock)))
2151 if (checkKind == LoaderLockCheck::None)
2154 // If we are checking whether the OS loader lock is held by the current thread, then
2155 // it better not be. Note that ShouldCheckLoaderLock is a cached test for whether
2156 // we are checking this probe. So we can call AuxUlibIsDLLSynchronizationHeld before
2157 // verifying that the probe is still enabled.
2159 // What's the difference between ignoreLoaderLock & ShouldCheckLoaderLock?
2160 // ShouldCheckLoaderLock is a process-wide flag. In a few places where we
2161 // *know* we are in the loader lock but haven't quite reached the dangerous
2162 // point, we call CanRunManagedCode suppressing/deferring this check.
2165 if (ShouldCheckLoaderLock(FALSE) &&
2166 AuxUlibIsDLLSynchronizationHeld(&IsHeld) &&
2169 if (checkKind == LoaderLockCheck::ForMDA)
2171 MDA_TRIGGER_ASSISTANT(LoaderLock, ReportViolation(hInst));
2178 #endif // defined(FEATURE_COMINTEROP) && defined(MDA_SUPPORTED)
2183 #include <optsmallperfcritical.h>
2184 BOOL CanRunManagedCode(LoaderLockCheck::kind checkKind, HINSTANCE hInst /*= 0*/)
2188 if (checkKind == LoaderLockCheck::ForMDA) { GC_TRIGGERS; } else { GC_NOTRIGGER; }; // because of the CustomerDebugProbe
2192 // Special-case the common success cases
2193 // (Try not to make any calls here so that we don't have to spill our incoming arg regs)
2194 if (!g_fForbidEnterEE
2195 && (g_pPreallocatedOutOfMemoryException != NULL)
2196 && !(g_fEEShutDown & ShutDown_Finalize2)
2197 && (((checkKind == LoaderLockCheck::ForMDA)
2198 #ifdef MDA_SUPPORTED
2199 && (NULL == MDA_GET_ASSISTANT(LoaderLock))
2200 #endif // MDA_SUPPORTED
2201 ) || (checkKind == LoaderLockCheck::None)))
2206 // Then call a helper for everything else.
2207 return CanRunManagedCodeRare(checkKind, hInst);
2209 #include <optdefault.h>
2212 // ---------------------------------------------------------------------------
2213 // %%Function: CoInitializeEE(DWORD fFlags)
2216 // fFlags - Initialization flags for the engine. See the
2217 // COINITIEE enumerator for valid values.
2223 // Initializes the EE if it hasn't already been initialized. This function
2224 // no longer maintains a ref count since the EE doesn't support being
2225 // unloaded and re-loaded. It simply ensures the EE has been started.
2226 // ---------------------------------------------------------------------------
2227 HRESULT STDAPICALLTYPE CoInitializeEE(DWORD fFlags)
2238 BEGIN_ENTRYPOINT_NOTHROW;
2239 hr = InitializeEE((COINITIEE)fFlags);
2240 END_ENTRYPOINT_NOTHROW;
2245 // ---------------------------------------------------------------------------
2246 // %%Function: CoUninitializeEE
2249 // BOOL fIsDllUnloading :: is it safe point for full cleanup
2255 // Must be called by client on shut down in order to free up the system.
2256 // ---------------------------------------------------------------------------
2257 void STDAPICALLTYPE CoUninitializeEE(BOOL fIsDllUnloading)
2259 LIMITED_METHOD_CONTRACT;
2260 //BEGIN_ENTRYPOINT_VOIDRET;
2262 // This API is unfortunately publicly exported so we cannot get rid
2263 // of it. However since the EE doesn't currently support being unloaded
2264 // and re-loaded, it is useless to do any ref counting here or to pretend
2265 // to unload it. The proper way to shutdown the EE is to call CorExitProcess.
2266 //END_ENTRYPOINT_VOIDRET;
2270 //*****************************************************************************
2271 BOOL ExecuteDLL_ReturnOrThrow(HRESULT hr, BOOL fFromThunk)
2274 if (fFromThunk) THROWS; else NOTHROW;
2275 WRAPPER(GC_TRIGGERS);
2279 // If we have a failure result, and we're called from a thunk,
2280 // then we need to throw an exception to communicate the error.
2281 if (FAILED(hr) && fFromThunk)
2285 return SUCCEEDED(hr);
2289 // Initialize the Garbage Collector
2292 void InitializeGarbageCollector()
2302 // Build the special Free Object used by the Generational GC
2303 _ASSERT(g_pFreeObjectMethodTable == NULL);
2304 g_pFreeObjectMethodTable = (MethodTable *) new BYTE[sizeof(MethodTable)];
2305 ZeroMemory(g_pFreeObjectMethodTable, sizeof(MethodTable));
2307 // As the flags in the method table indicate there are no pointers
2308 // in the object, there is no gc descriptor, and thus no need to adjust
2309 // the pointer to skip the gc descriptor.
2311 g_pFreeObjectMethodTable->SetBaseSize(ARRAYBASE_BASESIZE);
2312 g_pFreeObjectMethodTable->SetComponentSize(1);
2314 hr = GCHeapUtilities::LoadAndInitialize();
2320 // Apparently the Windows linker removes global variables if they are never
2321 // read from, which is a problem for g_gcDacGlobals since it's expected that
2322 // only the DAC will read from it. This forces the linker to include
2324 volatile void* _dummy = g_gcDacGlobals;
2327 /*****************************************************************************/
2328 /* This is here only so that if we get an exception we stop before we catch it */
2329 LONG DllMainFilter(PEXCEPTION_POINTERS p, PVOID pv)
2331 LIMITED_METHOD_CONTRACT;
2332 _ASSERTE(!"Exception happened in mscorwks!DllMain!");
2333 return EXCEPTION_EXECUTE_HANDLER;
2336 //*****************************************************************************
2337 // This is the part of the old-style DllMain that initializes the
2338 // stuff that the EE team works on. It's called from the real DllMain
2339 // up in MSCOREE land. Separating the DllMain tasks is simply for
2340 // convenience due to the dual build trees.
2341 //*****************************************************************************
2342 BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error.
2343 HINSTANCE hInst, // Instance handle of the loaded module.
2344 DWORD dwReason, // Reason for loading.
2345 LPVOID lpReserved) // Unused.
2347 STATIC_CONTRACT_NOTHROW;
2348 STATIC_CONTRACT_GC_TRIGGERS;
2351 // BEGIN_EXTERNAL_ENTRYPOINT(&hr);
2352 // EE isn't spun up enough to use this macro
2361 param.hInst = hInst;
2362 param.dwReason = dwReason;
2363 param.lpReserved = lpReserved;
2364 param.pTlsData = NULL;
2366 // Can't use PAL_TRY/EX_TRY here as they access the ClrDebugState which gets blown away as part of the
2367 // PROCESS_DETACH path. Must use special PAL_TRY_FOR_DLLMAIN, passing the reason were in the DllMain.
2368 PAL_TRY_FOR_DLLMAIN(Param *, pParam, ¶m, pParam->dwReason)
2371 switch (pParam->dwReason)
2373 case DLL_PROCESS_ATTACH:
2375 // We cache the SystemInfo for anyone to use throughout the
2377 GetSystemInfo(&g_SystemInfo);
2379 // Remember module instance
2380 g_pMSCorEE = pParam->hInst;
2383 // Set callbacks so that LoadStringRC knows which language our
2384 // threads are in so that it can return the proper localized string.
2385 // TODO: This shouldn't rely on the LCID (id), but only the name
2386 SetResourceCultureCallbacks(GetThreadUICultureNames,
2387 GetThreadUICultureId);
2394 case DLL_PROCESS_DETACH:
2396 // lpReserved is NULL if we're here because someone called FreeLibrary
2397 // and non-null if we're here because the process is exiting.
2398 // Since nobody should ever be calling FreeLibrary on mscorwks.dll, lpReserved
2399 // should always be non NULL.
2400 _ASSERTE(pParam->lpReserved || !g_fEEStarted);
2401 g_fProcessDetach = TRUE;
2405 // GetThread() may be set to NULL for Win9x during shutdown.
2406 Thread *pThread = GetThread();
2407 if (GCHeapUtilities::IsGCInProgress() &&
2408 ( (pThread && (pThread != ThreadSuspend::GetSuspensionThread() ))
2409 || !g_fSuspendOnShutdown))
2411 g_fEEShutDown |= ShutDown_Phase2;
2415 LOG((LF_STARTUP, INFO3, "EEShutDown invoked from EEDllMain"));
2416 EEShutDown(TRUE); // shut down EE if it was started up
2420 CLRRemoveVectoredHandlers();
2425 case DLL_THREAD_DETACH:
2427 // Don't destroy threads here if we're in shutdown (shutdown will
2428 // clean up for us instead).
2430 // Store the TLS data; we'll need it later and we might NULL the slot in DetachThread.
2431 // This would be problematic because we can't depend on the FLS still existing.
2432 pParam->pTlsData = CExecutionEngine::CheckThreadStateNoCreate(0
2434 // When we get here, OS has destroyed FLS, so FlsGetValue returns NULL now.
2435 // We have validation code in CExecutionEngine::CheckThreadStateNoCreate to ensure that
2436 // our TLS and FLS data are consistent, but since FLS has been destroyed, we need
2437 // to silent the check there. The extra arg for check build is for this purpose.
2441 Thread* thread = GetThread();
2444 #ifdef FEATURE_COMINTEROP
2445 // reset the CoInitialize state
2446 // so we don't call CoUninitialize during thread detach
2447 thread->ResetCoInitialized();
2448 #endif // FEATURE_COMINTEROP
2449 // For case where thread calls ExitThread directly, we need to reset the
2450 // frame pointer. Otherwise stackwalk would AV. We need to do it in cooperative mode.
2451 // We need to set m_GCOnTransitionsOK so this thread won't trigger GC when toggle GC mode
2452 if (thread->m_pFrame != FRAME_TOP)
2455 thread->m_GCOnTransitionsOK = FALSE;
2458 thread->m_pFrame = FRAME_TOP;
2459 GCX_COOP_NO_DTOR_END();
2461 thread->DetachThread(TRUE);
2467 PAL_EXCEPT_FILTER(DllMainFilter)
2472 if (dwReason == DLL_THREAD_DETACH || dwReason == DLL_PROCESS_DETACH)
2474 CExecutionEngine::ThreadDetaching(param.pTlsData);
2479 #ifdef DEBUGGING_SUPPORTED
2481 // InitializeDebugger initialized the Runtime-side COM+ Debugging Services
2483 static void InitializeDebugger(void)
2493 // Ensure that if we throw, we'll call TerminateDebugger to cleanup.
2494 // This makes our Init more atomic by avoiding partially-init states.
2495 class EnsureCleanup {
2500 fNeedCleanup = TRUE;
2503 void SuppressCleanup()
2505 fNeedCleanup = FALSE;
2510 STATIC_CONTRACT_NOTHROW;
2511 STATIC_CONTRACT_GC_NOTRIGGER;
2512 STATIC_CONTRACT_MODE_ANY;
2516 TerminateDebugger();
2523 LOG((LF_CORDB, LL_INFO10, "Initializing left-side debugging services.\n"));
2525 FARPROC gi = (FARPROC) &CorDBGetInterface;
2527 // Init the interface the EE provides to the debugger,
2528 // ask the debugger for its interface, and if all goes
2529 // well call Startup on the debugger.
2530 EEDbgInterfaceImpl::Init();
2531 _ASSERTE(g_pEEDbgInterfaceImpl != NULL); // throws on OOM
2533 // This allocates the Debugger object.
2534 typedef HRESULT __cdecl CORDBGETINTERFACE(DebugInterface**);
2535 hr = ((CORDBGETINTERFACE*)gi)(&g_pDebugInterface);
2538 g_pDebugInterface->SetEEInterface(g_pEEDbgInterfaceImpl);
2541 hr = g_pDebugInterface->Startup(); // throw on error
2542 _ASSERTE(SUCCEEDED(hr));
2545 // If the debug pack is not installed, Startup will return S_FALSE
2546 // and we should cleanup and proceed without debugging support.
2555 LOG((LF_CORDB, LL_INFO10, "Left-side debugging services setup.\n"));
2557 hCleanup.SuppressCleanup();
2564 // TerminateDebugger shuts down the Runtime-side COM+ Debugging Services
2565 // InitializeDebugger will call this if it fails.
2566 // This may be called even if the debugger is partially initialized.
2567 // This can be called multiple times.
2569 static void TerminateDebugger(void)
2579 LOG((LF_CORDB, LL_INFO10, "Shutting down left-side debugger services.\n"));
2581 // If initialized failed really early, then we didn't even get the Debugger object.
2582 if (g_pDebugInterface != NULL)
2584 // Notify the out-of-process debugger that shutdown of the in-process debugging support has begun. This is only
2585 // really used in interop debugging scenarios.
2586 g_pDebugInterface->ShutdownBegun();
2588 // This will kill the helper thread, delete the Debugger object, and free all resources.
2589 g_pDebugInterface->StopDebugger();
2592 g_CORDebuggerControlFlags = DBCF_NORMAL_OPERATION;
2596 #endif // DEBUGGING_SUPPORTED
2598 #ifndef LOCALE_SPARENT
2599 #define LOCALE_SPARENT 0x0000006d
2602 // ---------------------------------------------------------------------------
2603 // Impl for UtilLoadStringRC Callback: In VM, we let the thread decide culture
2604 // copy culture name into szBuffer and return length
2605 // ---------------------------------------------------------------------------
2606 extern BOOL g_fFatalErrorOccuredOnGCThread;
2607 static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames)
2614 PRECONDITION(CheckPointer(pCultureNames));
2622 InlineSString<LOCALE_NAME_MAX_LENGTH> sCulture;
2623 InlineSString<LOCALE_NAME_MAX_LENGTH> sParentCulture;
2625 #if 0 // Enable and test if/once the unmanaged runtime is localized
2626 Thread * pThread = GetThread();
2628 // When fatal errors have occured our invariants around GC modes may be broken and attempting to transition to co-op may hang
2629 // indefinately. We want to ensure a clean exit so rather than take the risk of hang we take a risk of the error resource not
2630 // getting localized with a non-default thread-specific culture.
2631 // A canonical stack trace that gets here is a fatal error in the GC that comes through:
2632 // coreclr.dll!GetThreadUICultureNames
2633 // coreclr.dll!CCompRC::LoadLibraryHelper
2634 // coreclr.dll!CCompRC::LoadLibrary
2635 // coreclr.dll!CCompRC::GetLibrary
2636 // coreclr.dll!CCompRC::LoadString
2637 // coreclr.dll!CCompRC::LoadString
2638 // coreclr.dll!SString::LoadResourceAndReturnHR
2639 // coreclr.dll!SString::LoadResourceAndReturnHR
2640 // coreclr.dll!SString::LoadResource
2641 // coreclr.dll!EventReporter::EventReporter
2642 // coreclr.dll!EEPolicy::LogFatalError
2643 // coreclr.dll!EEPolicy::HandleFatalError
2644 if (pThread != NULL && !g_fFatalErrorOccuredOnGCThread) {
2646 // Switch to cooperative mode, since we'll be looking at managed objects
2647 // and we don't want them moving on us.
2650 CULTUREINFOBASEREF pCurrentCulture = (CULTUREINFOBASEREF)Thread::GetCulture(TRUE);
2652 if (pCurrentCulture != NULL)
2654 STRINGREF cultureName = pCurrentCulture->GetName();
2656 if (cultureName != NULL)
2658 sCulture.Set(cultureName->GetBuffer(),cultureName->GetStringLength());
2661 CULTUREINFOBASEREF pParentCulture = pCurrentCulture->GetParent();
2663 if (pParentCulture != NULL)
2665 STRINGREF parentCultureName = pParentCulture->GetName();
2667 if (parentCultureName != NULL)
2669 sParentCulture.Set(parentCultureName->GetBuffer(),parentCultureName->GetStringLength());
2677 // If the lazily-initialized cultureinfo structures aren't initialized yet, we'll
2678 // need to do the lookup the hard way.
2679 if (sCulture.IsEmpty() || sParentCulture.IsEmpty())
2682 int tmp; tmp = GetThreadUICultureId(&id); // TODO: We should use the name instead
2683 _ASSERTE(tmp!=0 && id != UICULTUREID_DONTCARE);
2684 SIZE_T cchParentCultureName=LOCALE_NAME_MAX_LENGTH;
2685 #ifdef FEATURE_USE_LCID
2686 SIZE_T cchCultureName=LOCALE_NAME_MAX_LENGTH;
2687 if (!::LCIDToLocaleName(id, sCulture.OpenUnicodeBuffer(static_cast<COUNT_T>(cchCultureName)), static_cast<int>(cchCultureName), 0))
2689 hr = HRESULT_FROM_GetLastError();
2691 sCulture.CloseBuffer();
2697 if (!::GetLocaleInfoEx((LPCWSTR)sCulture, LOCALE_SPARENT, sParentCulture.OpenUnicodeBuffer(static_cast<COUNT_T>(cchParentCultureName)),static_cast<int>(cchParentCultureName)))
2699 hr = HRESULT_FROM_GetLastError();
2701 sParentCulture.CloseBuffer();
2702 #else // !FEATURE_PAL
2703 sParentCulture = sCulture;
2704 #endif // !FEATURE_PAL
2706 // (LPCWSTR) to restrict the size to null terminated size
2707 pCultureNames->AppendIfNotThere((LPCWSTR)sCulture);
2708 // Disabling for Dev10 for consistency with managed resource lookup (see AppCompat bug notes in ResourceFallbackManager.cs)
2709 // Also, this is in the wrong order - put after the parent culture chain.
2710 //AddThreadPreferredUILanguages(pCultureNames);
2711 pCultureNames->AppendIfNotThere((LPCWSTR)sParentCulture);
2712 pCultureNames->Append(SString::Empty());
2718 EX_END_CATCH(SwallowAllExceptions);
2723 // The exit code for the process is communicated in one of two ways. If the
2724 // entrypoint returns an 'int' we take that. Otherwise we take a latched
2725 // process exit code. This can be modified by the app via System.SetExitCode().
2726 static INT32 LatchedExitCode;
2728 void SetLatchedExitCode (INT32 code)
2738 STRESS_LOG1(LF_SYNC, LL_INFO10, "SetLatchedExitCode = %d\n", code);
2739 LatchedExitCode = code;
2742 INT32 GetLatchedExitCode (void)
2744 LIMITED_METHOD_CONTRACT;
2745 return LatchedExitCode;
2749 // ---------------------------------------------------------------------------
2750 // Impl for UtilLoadStringRC Callback: In VM, we let the thread decide culture
2751 // Return an int uniquely describing which language this thread is using for ui.
2752 // ---------------------------------------------------------------------------
2753 // TODO: Callers should use names, not LCIDs
2754 #ifdef FEATURE_USE_LCID
2755 static int GetThreadUICultureId(__out LocaleIDValue* pLocale)
2765 int Result = UICULTUREID_DONTCARE;
2767 Thread * pThread = GetThread();
2769 #if 0 // Enable and test if/once the unmanaged runtime is localized
2770 // When fatal errors have occured our invariants around GC modes may be broken and attempting to transition to co-op may hang
2771 // indefinately. We want to ensure a clean exit so rather than take the risk of hang we take a risk of the error resource not
2772 // getting localized with a non-default thread-specific culture.
2773 // A canonical stack trace that gets here is a fatal error in the GC that comes through:
2774 // coreclr.dll!GetThreadUICultureNames
2775 // coreclr.dll!CCompRC::LoadLibraryHelper
2776 // coreclr.dll!CCompRC::LoadLibrary
2777 // coreclr.dll!CCompRC::GetLibrary
2778 // coreclr.dll!CCompRC::LoadString
2779 // coreclr.dll!CCompRC::LoadString
2780 // coreclr.dll!SString::LoadResourceAndReturnHR
2781 // coreclr.dll!SString::LoadResourceAndReturnHR
2782 // coreclr.dll!SString::LoadResource
2783 // coreclr.dll!EventReporter::EventReporter
2784 // coreclr.dll!EEPolicy::LogFatalError
2785 // coreclr.dll!EEPolicy::HandleFatalError
2786 if (pThread != NULL && !g_fFatalErrorOccuredOnGCThread)
2788 // Switch to cooperative mode, since we'll be looking at managed objects
2789 // and we don't want them moving on us.
2792 CULTUREINFOBASEREF pCurrentCulture = (CULTUREINFOBASEREF)Thread::GetCulture(TRUE);
2794 if (pCurrentCulture != NULL)
2796 STRINGREF cultureName = pCurrentCulture->GetName();
2797 _ASSERT(cultureName != NULL);
2799 if ((Result = ::LocaleNameToLCID(cultureName->GetBuffer(), 0)) == 0)
2800 Result = (int)UICULTUREID_DONTCARE;
2805 if (Result == (int)UICULTUREID_DONTCARE)
2807 // This thread isn't set up to use a non-default culture. Let's grab the default
2808 // one and return that.
2810 Result = COMNlsInfo::CallGetUserDefaultUILanguage();
2812 if (Result == 0 || Result == (int)UICULTUREID_DONTCARE)
2813 Result = GetUserDefaultLangID();
2815 _ASSERTE(Result != 0);
2818 Result = (int)UICULTUREID_DONTCARE;
2826 // TODO: Callers should use names, not LCIDs
2827 static int GetThreadUICultureId(__out LocaleIDValue* pLocale)
2835 _ASSERTE(sizeof(LocaleIDValue)/sizeof(WCHAR) >= LOCALE_NAME_MAX_LENGTH);
2839 Thread * pThread = GetThread();
2841 #if 0 // Enable and test if/once the unmanaged runtime is localized
2842 // When fatal errors have occured our invariants around GC modes may be broken and attempting to transition to co-op may hang
2843 // indefinately. We want to ensure a clean exit so rather than take the risk of hang we take a risk of the error resource not
2844 // getting localized with a non-default thread-specific culture.
2845 // A canonical stack trace that gets here is a fatal error in the GC that comes through:
2846 // coreclr.dll!GetThreadUICultureNames
2847 // coreclr.dll!CCompRC::LoadLibraryHelper
2848 // coreclr.dll!CCompRC::LoadLibrary
2849 // coreclr.dll!CCompRC::GetLibrary
2850 // coreclr.dll!CCompRC::LoadString
2851 // coreclr.dll!CCompRC::LoadString
2852 // coreclr.dll!SString::LoadResourceAndReturnHR
2853 // coreclr.dll!SString::LoadResourceAndReturnHR
2854 // coreclr.dll!SString::LoadResource
2855 // coreclr.dll!EventReporter::EventReporter
2856 // coreclr.dll!EEPolicy::LogFatalError
2857 // coreclr.dll!EEPolicy::HandleFatalError
2858 if (pThread != NULL && !g_fFatalErrorOccuredOnGCThread)
2861 // Switch to cooperative mode, since we'll be looking at managed objects
2862 // and we don't want them moving on us.
2865 CULTUREINFOBASEREF pCurrentCulture = (CULTUREINFOBASEREF)Thread::GetCulture(TRUE);
2867 if (pCurrentCulture != NULL)
2869 STRINGREF currentCultureName = pCurrentCulture->GetName();
2871 if (currentCultureName != NULL)
2873 int cchCurrentCultureNameResult = currentCultureName->GetStringLength();
2874 if (cchCurrentCultureNameResult < LOCALE_NAME_MAX_LENGTH)
2876 memcpy(*pLocale, currentCultureName->GetBuffer(), cchCurrentCultureNameResult*sizeof(WCHAR));
2877 (*pLocale)[cchCurrentCultureNameResult]='\0';
2878 Result=cchCurrentCultureNameResult;
2887 // This thread isn't set up to use a non-default culture. Let's grab the default
2888 // one and return that.
2890 Result = ::GetUserDefaultLocaleName(*pLocale, LOCALE_NAME_MAX_LENGTH);
2892 _ASSERTE(Result != 0);
2893 #else // !FEATURE_PAL
2894 static const WCHAR enUS[] = W("en-US");
2895 memcpy(*pLocale, enUS, sizeof(enUS));
2896 Result = sizeof(enUS);
2897 #endif // !FEATURE_PAL
2902 #endif // FEATURE_USE_LCID
2905 #ifdef ENABLE_CONTRACTS_IMPL
2907 // Returns TRUE if any contract violation suppressions are in effect.
2908 BOOL AreAnyViolationBitsOn()
2917 UINT_PTR violationMask = GetClrDebugState()->ViolationMask();
2918 violationMask &= ~((UINT_PTR)CanFreeMe); //CanFreeMe is a borrowed bit and has nothing to do with violations
2919 if (violationMask & ((UINT_PTR)BadDebugState))
2924 return violationMask != 0;
2928 // This function is intentionally invoked inside a big CONTRACT_VIOLATION that turns on every violation
2929 // bit on the map. The dynamic contract at the beginning *should* turn off those violation bits.
2930 // The body of this function tests to see that it did exactly that. This is to prevent the VSWhidbey B#564831 fiasco
2931 // from ever recurring.
2932 void ContractRegressionCheckInner()
2934 // DO NOT TURN THIS CONTRACT INTO A STATIC CONTRACT!!! The very purpose of this function
2935 // is to ensure that dynamic contracts disable outstanding contract violation bits.
2936 // This code only runs once at process startup so it's not going pooch the checked build perf.
2942 LOADS_TYPE(CLASS_LOAD_BEGIN);
2947 if (AreAnyViolationBitsOn())
2949 // If we got here, the contract above FAILED to turn off one or more violation bits. This is a
2950 // huge diagnostics hole and must be fixed immediately.
2951 _ASSERTE(!("WARNING: mscorwks has detected an internal error that may indicate contracts are"
2952 " being silently disabled across the runtime. Do not ignore this assert!"));
2956 // This function executes once per process to ensure our CONTRACT_VIOLATION() mechanism
2957 // is properly scope-limited by nested contracts.
2958 void ContractRegressionCheck()
2969 // DO NOT "FIX" THIS CONTRACT_VIOLATION!!!
2970 // The existence of this CONTRACT_VIOLATION is not a bug. This is debug-only code specifically written
2971 // to test the CONTRACT_VIOLATION mechanism itself. This is needed to prevent a regression of
2972 // B#564831 (which left a huge swath of contracts silently disabled for over six months)
2973 PERMANENT_CONTRACT_VIOLATION(ThrowsViolation
2976 | LoadsTypeViolation
2977 | TakesLockViolation
2978 , ReasonContractInfrastructure
2982 ContractRegressionCheckInner();
2986 if (AreAnyViolationBitsOn())
2988 // If we got here, the CONTRACT_VIOLATION() holder left one or more violation bits turned ON
2989 // after we left its scope. This is a huge diagnostic hole and must be fixed immediately.
2990 _ASSERTE(!("WARNING: mscorwks has detected an internal error that may indicate contracts are"
2991 " being silently disabled across the runtime. Do not ignore this assert!"));
2996 #endif // ENABLE_CONTRACTS_IMPL
2998 #endif // CROSSGEN_COMPILE