Prevent freeing of the profiler on process shutdown.
[platform/upstream/coreclr.git] / src / vm / ceemain.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // ===========================================================================
5 // File: CEEMAIN.CPP
6 // ===========================================================================
7 //
8
9 // 
10 //
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 
13 // 
14 //     \\clrmain\tools\installCLRAddins
15 //     
16 //  After installing HyperAddin, your first run of VS should be as an administrator so HyperAddin can update 
17 //  some registry information.
18 //     
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
21 //  
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.
26 // 
27 // #StartHere
28 // #TableOfContents The .NET Runtime Table of contents
29 // 
30 // This comment is mean to be a nexus that allows you to jump quickly to various interesting parts of the
31 // runtime.
32 // 
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
36 //     
37 //  Dev10 Bugs can be added with URLs like the following (for Dev10 bug 671409)
38 //     * http://tkbgitvstfat01:8090/wi.aspx?id=671409
39 // 
40 //*************************************************************************************************
41 //
42 // * Introduction to the runtime file:../../Documentation/botr/botr-faq.md
43 //
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 
54 // 
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
60 //     * Partition III IL
61 //         http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20III%20CIL.doc
62 //  
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
65 // 
66 // * This is also a pretty nice overview of what the CLR is at
67 //     http://msdn2.microsoft.com/en-us/netframework/aa497266.aspx
68 // 
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.
72 //     
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.
75 //  
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.
80 // 
81 // * code:VirtualCallStubManager - This is the main class that implements interface dispatch
82 // 
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.
86 //     
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
90 //      NGEN image.
91 //      
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
99 //       exception happens.
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.
112
113 // ----------------------------------------------------------------------------------------------------
114 // Features in the runtime that have been given hyperlinks
115 // 
116 // * code:Nullable#NullableFeature - the Nullable<T> type has special runtime semantics associated with
117 //     boxing this describes this feature.
118
119 #include "common.h"
120
121 #include "vars.hpp"
122 #include "log.h"
123 #include "ceemain.h"
124 #include "clsload.hpp"
125 #include "object.h"
126 #include "hash.h"
127 #include "ecall.h"
128 #include "ceemain.h"
129 #include "dllimport.h"
130 #include "syncblk.h"
131 #include "eeconfig.h"
132 #include "stublink.h"
133 #include "method.hpp"
134 #include "codeman.h"
135 #include "frames.h"
136 #include "threads.h"
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"
148 #include "corhost.h"
149 #include "binder.h"
150 #include "olevariant.h"
151 #include "comcallablewrapper.h"
152 #include "apithreadstress.h"
153 #include "perflog.h"
154 #include "../dlls/mscorrc/resource.h"
155 #include "util.hpp"
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 "eemessagebox.h"
165 #include "finalizerthread.h"
166 #include "threadsuspend.h"
167 #include "disassembler.h"
168 #include "jithost.h"
169
170 #ifndef FEATURE_PAL
171 #include "dwreport.h"
172 #endif // !FEATURE_PAL
173
174 #include "stringarraylist.h"
175 #include "stubhelpers.h"
176
177 #ifdef FEATURE_STACK_SAMPLING
178 #include "stacksampler.h"
179 #endif
180
181 #include <shlwapi.h>
182
183 #include "bbsweep.h"
184
185
186 #ifdef FEATURE_COMINTEROP
187 #include "runtimecallablewrapper.h"
188 #include "notifyexternals.h"
189 #include "mngstdinterfaces.h"
190 #include "rcwwalker.h"
191 #endif // FEATURE_COMINTEROP
192
193 #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
194 #include "olecontexthelpers.h"
195 #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
196
197 #ifdef PROFILING_SUPPORTED
198 #include "proftoeeinterfaceimpl.h"
199 #include "profilinghelper.h"
200 #endif // PROFILING_SUPPORTED
201
202 #ifdef FEATURE_COMINTEROP
203 #include "synchronizationcontextnative.h"       // For SynchronizationContextNative::Cleanup
204 #endif
205
206 #ifdef FEATURE_INTERPRETER
207 #include "interpreter.h"
208 #endif // FEATURE_INTERPRETER
209
210 #include "../binder/inc/coreclrbindercommon.h"
211
212
213 #ifdef FEATURE_PERFMAP
214 #include "perfmap.h"
215 #endif
216
217 #include "diagnosticserver.h"
218 #include "eventpipe.h"
219
220 #ifndef FEATURE_PAL
221 // Included for referencing __security_cookie
222 #include "process.h"
223 #endif // !FEATURE_PAL
224
225 #ifdef FEATURE_GDBJIT
226 #include "gdbjit.h"
227 #endif // FEATURE_GDBJIT
228
229 #ifndef CROSSGEN_COMPILE
230 static int GetThreadUICultureId(__out LocaleIDValue* pLocale);  // TODO: This shouldn't use the LCID.  We should rely on name instead
231
232 static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames);
233 #endif // !CROSSGEN_COMPILE
234
235 HRESULT EEStartup(COINITIEE fFlags);
236
237
238 #ifndef CROSSGEN_COMPILE
239 static void InitializeGarbageCollector();
240
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
247
248
249
250
251 // Remember how the last startup of EE went.
252 HRESULT g_EEStartupStatus = S_OK;
253
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;
258
259 // Flag indicating if the EE was started up by COM.
260 extern BOOL g_fEEComActivatedStartup;
261
262 // flag indicating that EE was not started up by IJW, Hosted, COM or my managed exe. 
263 extern BOOL g_fEEOtherStartup;
264
265 // The OS thread ID of the thread currently performing EE startup, or 0 if there is no such thread.
266 DWORD   g_dwStartupThreadId = 0;
267
268 // Event to synchronize EE shutdown.
269 static CLREvent * g_pEEShutDownEvent;
270
271 static DangerousNonHostedSpinLock g_EEStartupLock;
272
273 HRESULT InitializeEE(COINITIEE flags)
274 {
275     WRAPPER_NO_CONTRACT;
276 #ifdef FEATURE_EVENT_TRACE
277     if(!g_fEEComActivatedStartup)
278         g_fEEOtherStartup = TRUE;
279 #endif // FEATURE_EVENT_TRACE
280     return EnsureEEStarted(flags);
281 }
282
283 // ---------------------------------------------------------------------------
284 // %%Function: EnsureEEStarted()
285 //
286 // Description: Ensure the CLR is started.
287 // ---------------------------------------------------------------------------
288 HRESULT EnsureEEStarted(COINITIEE flags)
289 {
290     CONTRACTL
291     {
292         NOTHROW;
293         GC_TRIGGERS;
294         MODE_PREEMPTIVE;
295         ENTRY_POINT;
296     }
297     CONTRACTL_END;
298
299     if (g_fEEShutDown)
300         return E_FAIL;
301
302     HRESULT hr = E_FAIL;
303
304     // On non x86 platforms, when we load mscorlib.dll during EEStartup, we will
305     // re-enter _CorDllMain with a DLL_PROCESS_ATTACH for mscorlib.dll. We are
306     // far enough in startup that this is allowed, however we don't want to
307     // re-start the startup code so we need to check to see if startup has
308     // been initiated or completed before we call EEStartup. 
309     //
310     // We do however want to make sure other threads block until the EE is started,
311     // which we will do further down.
312     if (!g_fEEStarted)
313     {
314         BEGIN_ENTRYPOINT_NOTHROW;
315
316 #if defined(FEATURE_APPX) && !defined(CROSSGEN_COMPILE)
317         STARTUP_FLAGS startupFlags = CorHost2::GetStartupFlags();
318         // On CoreCLR, the host is in charge of determining whether the process is AppX or not.
319         AppX::SetIsAppXProcess(!!(startupFlags & STARTUP_APPX_APP_MODEL));
320 #endif
321
322 #ifndef FEATURE_PAL
323         // The sooner we do this, the sooner we avoid probing registry entries.
324         // (Perf Optimization for VSWhidbey:113373.)
325         REGUTIL::InitOptionalConfigCache();
326 #endif
327
328
329         BOOL bStarted=FALSE;
330
331         {
332             DangerousNonHostedSpinLockHolder lockHolder(&g_EEStartupLock);
333
334             // Now that we've acquired the lock, check again to make sure we aren't in
335             // the process of starting the CLR or that it hasn't already been fully started.
336             // At this point, if startup has been inited we don't have anything more to do.
337             // And if EEStartup already failed before, we don't do it again.
338             if (!g_fEEStarted && !g_fEEInit && SUCCEEDED (g_EEStartupStatus))
339             {
340                 g_dwStartupThreadId = GetCurrentThreadId();
341
342                 EEStartup(flags);
343                 bStarted=g_fEEStarted;
344                 hr = g_EEStartupStatus;
345
346                 g_dwStartupThreadId = 0;
347             }
348             else
349             {
350                 hr = g_EEStartupStatus;
351                 if (SUCCEEDED(g_EEStartupStatus))
352                 {
353                     hr = S_FALSE;
354                 }
355             }
356         }
357
358         END_ENTRYPOINT_NOTHROW;
359     }
360     else
361     {
362         //
363         // g_fEEStarted is TRUE, but startup may not be complete since we initialize the default AppDomain
364         // *after* setting that flag.  g_fEEStarted is set inside of g_EEStartupLock, and that lock is
365         // not released until the EE is really started - so we can quickly check whether the EE is definitely
366         // started by checking if that lock is currently held.  If it is not, then we know the other thread
367         // (that is actually doing the startup) has finished startup.  If it is currently held, then we
368         // need to wait for the other thread to release it, which we do by simply acquiring the lock ourselves.
369         //
370         // We do not want to do this blocking if we are the thread currently performing EE startup.  So we check
371         // that first.
372         //
373         // Note that the call to IsHeld here is an "acquire" barrier, as is acquiring the lock.  And the release of 
374         // the lock by the other thread is a "release" barrier, due to the volatile semantics in the lock's 
375         // implementation.  This assures us that once we observe the lock having been released, we are guaranteed 
376         // to observe a fully-initialized EE.
377         //
378         // A note about thread affinity here: we're using the OS thread ID of the current thread without
379         // asking the host to pin us to this thread, as we did above.  We can get away with this, because we are
380         // only interested in a particular thread ID (that of the "startup" thread) and *that* particular thread
381         // is already affinitized by the code above.  So if we get that particular OS thread ID, we know for sure
382         // we are really the startup thread.
383         //
384         if (g_EEStartupLock.IsHeld() && g_dwStartupThreadId != GetCurrentThreadId())
385         {
386             DangerousNonHostedSpinLockHolder lockHolder(&g_EEStartupLock);
387         }
388
389         hr = g_EEStartupStatus;
390         if (SUCCEEDED(g_EEStartupStatus))
391         {
392             hr = S_FALSE;
393         }
394     }
395
396     return hr;
397 }
398
399
400 #ifndef CROSSGEN_COMPILE
401
402 #ifndef FEATURE_PAL
403 // This is our Ctrl-C, Ctrl-Break, etc. handler.
404 static BOOL WINAPI DbgCtrlCHandler(DWORD dwCtrlType)
405 {
406     WRAPPER_NO_CONTRACT;
407
408 #if defined(DEBUGGING_SUPPORTED)
409     // Note that if a managed-debugger is attached, it's actually attached with the native
410     // debugging pipeline and it will get a control-c notifications via native debug events.
411     // However, if we let the native debugging pipeline handle the event and send the notification
412     // to the debugger, then we break pre-V4 behaviour because we intercept handlers registered
413     // in-process.  See Dev10 Bug 846455 for more information. 
414     if (CORDebuggerAttached() &&
415         (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT))
416     {
417         return g_pDebugInterface->SendCtrlCToDebugger(dwCtrlType);
418     }
419     else
420 #endif // DEBUGGING_SUPPORTED
421     {
422         if (dwCtrlType == CTRL_CLOSE_EVENT)
423         {
424             // Initiate shutdown so the ProcessExit handlers run
425             ForceEEShutdown(SCA_ReturnWhenShutdownComplete);
426         }
427
428         g_fInControlC = true;     // only for weakening assertions in checked build.
429         return FALSE;             // keep looking for a real handler.
430     }
431 }
432 #endif
433
434 // A host can specify that it only wants one version of hosting interface to be used.
435 BOOL g_singleVersionHosting;
436
437
438
439 void InitializeStartupFlags()
440 {
441     CONTRACTL {
442         NOTHROW;
443         GC_TRIGGERS;
444         MODE_ANY;
445     } CONTRACTL_END;
446
447     STARTUP_FLAGS flags = CorHost2::GetStartupFlags();
448
449
450     if (flags & STARTUP_CONCURRENT_GC)
451         g_IGCconcurrent = 1;
452     else
453         g_IGCconcurrent = 0;
454
455
456     g_heap_type = ((flags & STARTUP_SERVER_GC) && GetCurrentProcessCpuCount() > 1) ? GC_HEAP_SVR : GC_HEAP_WKS;
457     g_IGCHoardVM = (flags & STARTUP_HOARD_GC_VM) == 0 ? 0 : 1;
458 }
459 #endif // CROSSGEN_COMPILE
460
461
462 // BBSweepStartFunction is the first function to execute in the BBT sweeper thread.
463 // It calls WatchForSweepEvent where we wait until a sweep occurs.
464 DWORD __stdcall BBSweepStartFunction(LPVOID lpArgs)
465 {
466     CONTRACTL
467     {
468         THROWS;
469         GC_TRIGGERS;
470         MODE_PREEMPTIVE;
471     }
472     CONTRACTL_END;
473
474     class CLRBBSweepCallback : public ICLRBBSweepCallback
475     {
476         virtual HRESULT WriteProfileData()
477         {
478             BEGIN_ENTRYPOINT_NOTHROW
479             WRAPPER_NO_CONTRACT;
480             Module::WriteAllModuleProfileData(false);
481             END_ENTRYPOINT_NOTHROW;
482             return S_OK;
483         }
484     } clrCallback;
485
486     EX_TRY
487     {
488         g_BBSweep.WatchForSweepEvents(&clrCallback);
489     }
490     EX_CATCH
491     {
492     }
493     EX_END_CATCH(RethrowTerminalExceptions)
494
495     return 0;
496 }
497
498
499 //-----------------------------------------------------------------------------
500
501 void InitGSCookie()
502 {
503     CONTRACTL
504     {
505         THROWS;
506         GC_NOTRIGGER;
507         MODE_ANY;
508     }
509     CONTRACTL_END;
510
511     GSCookie * pGSCookiePtr = GetProcessGSCookiePtr();
512
513 #ifdef FEATURE_PAL
514     // On Unix, the GS cookie is stored in a read only data segment
515     DWORD newProtection = PAGE_READWRITE;
516 #else // FEATURE_PAL
517     DWORD newProtection = PAGE_EXECUTE_READWRITE;
518 #endif // !FEATURE_PAL
519
520     DWORD oldProtection;
521     if(!ClrVirtualProtect((LPVOID)pGSCookiePtr, sizeof(GSCookie), newProtection, &oldProtection))
522     {
523         ThrowLastError();
524     }
525
526 #ifdef FEATURE_PAL
527     // PAL layer is unable to extract old protection for regions that were not allocated using VirtualAlloc
528     oldProtection = PAGE_READONLY;
529 #endif // FEATURE_PAL
530
531 #ifndef FEATURE_PAL
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));
535
536     // Forces VC cookie to be initialized.
537     void * pf = &__security_check_cookie;
538     pf = NULL;
539
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
545
546 #ifdef _DEBUG
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);
549 #endif
550
551     // To test if it is initialized. Also for ICorMethodInfo::getGSCookie()
552     if (val == 0)
553         val ++;
554     *pGSCookiePtr = val;
555
556     if(!ClrVirtualProtect((LPVOID)pGSCookiePtr, sizeof(GSCookie), oldProtection, &oldProtection))
557     {
558         ThrowLastError();
559     }
560 }
561
562 Volatile<BOOL> g_bIsGarbageCollectorFullyInitialized = FALSE;
563
564 void SetGarbageCollectorFullyInitialized()
565 {
566     LIMITED_METHOD_CONTRACT;
567
568     g_bIsGarbageCollectorFullyInitialized = TRUE;
569 }
570
571 // Tells whether the garbage collector is fully initialized
572 // Stronger than IsGCHeapInitialized
573 BOOL IsGarbageCollectorFullyInitialized()
574 {
575     LIMITED_METHOD_CONTRACT;
576
577     return g_bIsGarbageCollectorFullyInitialized;
578 }
579
580 // ---------------------------------------------------------------------------
581 // %%Function: EEStartupHelper
582 //
583 // Parameters:
584 //  fFlags                  - Initialization flags for the engine.  See the
585 //                              EEStartupFlags enumerator for valid values.
586 //
587 // Returns:
588 //  S_OK                    - On success
589 //
590 // Description:
591 //  Reserved to initialize the EE runtime engine explicitly.
592 // ---------------------------------------------------------------------------
593
594 #ifndef IfFailGotoLog
595 #define IfFailGotoLog(EXPR, LABEL) \
596 do { \
597     hr = (EXPR);\
598     if(FAILED(hr)) { \
599         STRESS_LOG2(LF_STARTUP, LL_ALWAYS, "%s failed with code %x", #EXPR, hr);\
600         goto LABEL; \
601     } \
602     else \
603        STRESS_LOG1(LF_STARTUP, LL_ALWAYS, "%s completed", #EXPR);\
604 } while (0)
605 #endif
606
607 #ifndef IfFailGoLog
608 #define IfFailGoLog(EXPR) IfFailGotoLog(EXPR, ErrExit)
609 #endif
610
611
612 #ifndef CROSSGEN_COMPILE
613 #ifdef FEATURE_PAL
614 void EESocketCleanupHelper()
615 {
616     CONTRACTL
617     {
618         GC_NOTRIGGER;
619         MODE_ANY;
620     } CONTRACTL_END;
621
622     // Close the debugger transport socket first
623     if (g_pDebugInterface != NULL)
624     {
625         g_pDebugInterface->CleanupTransportSocket();
626     }
627
628     // Close the diagnostic server socket.
629 #ifdef FEATURE_PERFTRACING
630     DiagnosticServer::Shutdown();
631 #endif // FEATURE_PERFTRACING
632 }
633 #endif // FEATURE_PAL
634 #endif // CROSSGEN_COMPILE
635
636 void EEStartupHelper(COINITIEE fFlags)
637 {
638     CONTRACTL
639     {
640         THROWS;
641         GC_TRIGGERS;
642         MODE_ANY;
643     } CONTRACTL_END;
644
645 #ifdef ENABLE_CONTRACTS_IMPL
646     {
647         extern void ContractRegressionCheck();
648         ContractRegressionCheck();
649     }
650 #endif
651
652     HRESULT hr = S_OK;
653     static ConfigDWORD breakOnEELoad;
654     EX_TRY
655     {
656         g_fEEInit = true;
657
658 #ifndef CROSSGEN_COMPILE
659
660 #ifndef FEATURE_PAL
661         ::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);
662 #endif
663
664 #endif // CROSSGEN_COMPILE
665
666         // SString initialization
667         // This needs to be done before config because config uses SString::Empty()
668         SString::Startup();
669
670         IfFailGo(EEConfig::Setup());
671
672 #ifndef CROSSGEN_COMPILE
673         // Initialize Numa and CPU group information
674         // Need to do this as early as possible. Used by creating object handle
675         // table inside Ref_Initialization() before GC is initialized.
676         NumaNodeInfo::InitNumaNodeInfo();
677 #ifndef FEATURE_PAL
678         CPUGroupInfo::EnsureInitialized();
679 #endif // !FEATURE_PAL
680
681         // Initialize global configuration settings based on startup flags
682         // This needs to be done before the EE has started
683         InitializeStartupFlags();
684
685         MethodDescBackpatchInfoTracker::StaticInitialize();
686
687         InitThreadManager();
688         STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "Returned successfully from InitThreadManager");
689
690 #ifdef FEATURE_PERFTRACING
691         // Initialize the event pipe.
692         EventPipe::Initialize();
693
694 #endif // FEATURE_PERFTRACING
695
696 #ifdef FEATURE_PAL
697         PAL_SetShutdownCallback(EESocketCleanupHelper);
698 #endif // FEATURE_PAL
699
700 #ifdef FEATURE_GDBJIT
701         // Initialize gdbjit
702         NotifyGdb::Initialize();
703 #endif // FEATURE_GDBJIT
704
705 #ifdef FEATURE_EVENT_TRACE        
706         // Initialize event tracing early so we can trace CLR startup time events.
707         InitializeEventTracing();
708
709         // Fire the EE startup ETW event
710         ETWFireEvent(EEStartupStart_V1);
711 #endif // FEATURE_EVENT_TRACE
712
713         InitGSCookie();
714
715         Frame::Init();
716
717 #endif // CROSSGEN_COMPILE
718
719
720 #ifdef STRESS_LOG
721         if (REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_StressLog, g_pConfig->StressLog ()) != 0) {
722             unsigned facilities = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_LogFacility, LF_ALL);
723             unsigned level = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::EXTERNAL_LogLevel, LL_INFO1000);
724             unsigned bytesPerThread = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_StressLogSize, STRESSLOG_CHUNK_SIZE * 4);
725             unsigned totalBytes = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_TotalStressLogSize, STRESSLOG_CHUNK_SIZE * 1024);
726             StressLog::Initialize(facilities, level, bytesPerThread, totalBytes, GetModuleInst());
727             g_pStressLog = &StressLog::theLog;
728         }
729 #endif
730
731 #ifdef LOGGING
732         InitializeLogging();
733 #endif
734
735 #ifdef ENABLE_PERF_LOG
736         PerfLog::PerfLogInitialize();
737 #endif //ENABLE_PERF_LOG
738
739 #ifdef FEATURE_PERFMAP
740         PerfMap::Initialize();
741 #endif
742
743         STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "===================EEStartup Starting===================");
744
745 #ifndef CROSSGEN_COMPILE
746 #ifndef FEATURE_PAL
747         IfFailGoLog(EnsureRtlFunctions());
748 #endif // !FEATURE_PAL
749         InitEventStore();
750 #endif
751
752         // Fusion
753         // Initialize the general Assembly Binder infrastructure
754         IfFailGoLog(CCoreCLRBinderHelper::Init());
755
756         if (g_pConfig != NULL)
757         {
758             IfFailGoLog(g_pConfig->sync());        
759         }
760
761         // Fire the runtime information ETW event
762         ETW::InfoLog::RuntimeInformation(ETW::InfoLog::InfoStructs::Normal);
763
764         if (breakOnEELoad.val(CLRConfig::UNSUPPORTED_BreakOnEELoad) == 1)
765         {
766 #ifdef _DEBUG
767             _ASSERTE(!"Start loading EE!");
768 #else
769             DebugBreak();
770 #endif
771         }
772
773 #ifdef ENABLE_STARTUP_DELAY
774         PREFIX_ASSUME(NULL != g_pConfig);
775         if (g_pConfig->StartupDelayMS())
776         {
777             ClrSleepEx(g_pConfig->StartupDelayMS(), FALSE);
778         }
779 #endif
780         
781 #if USE_DISASSEMBLER
782         if ((g_pConfig->GetGCStressLevel() & (EEConfig::GCSTRESS_INSTR_JIT | EEConfig::GCSTRESS_INSTR_NGEN)) != 0)
783         {
784             Disassembler::StaticInitialize();
785             if (!Disassembler::IsAvailable())
786             {
787                 fprintf(stderr, "External disassembler is not available.\n");
788                 IfFailGo(E_FAIL);
789             }
790         }
791 #endif // USE_DISASSEMBLER
792
793         // Monitors, Crsts, and SimpleRWLocks all use the same spin heuristics
794         // Cache the (potentially user-overridden) values now so they are accessible from asm routines
795         InitializeSpinConstants();
796
797 #ifndef CROSSGEN_COMPILE
798
799         // Cross-process named objects are not supported in PAL
800         // (see CorUnix::InternalCreateEvent - src/pal/src/synchobj/event.cpp.272)
801 #if !defined(FEATURE_PAL)
802         // Initialize the sweeper thread.
803         if (g_pConfig->GetZapBBInstr() != NULL)
804         {
805             DWORD threadID;
806             HANDLE hBBSweepThread = ::CreateThread(NULL,
807                                                    0,
808                                                    (LPTHREAD_START_ROUTINE) BBSweepStartFunction,
809                                                    NULL,
810                                                    0,
811                                                    &threadID);
812             _ASSERTE(hBBSweepThread);
813             g_BBSweep.SetBBSweepThreadHandle(hBBSweepThread);
814         }
815 #endif // FEATURE_PAL
816
817 #ifdef FEATURE_INTERPRETER
818         Interpreter::Initialize();
819 #endif // FEATURE_INTERPRETER
820
821         StubManager::InitializeStubManagers();
822
823 #ifndef FEATURE_PAL
824         {
825             // Record mscorwks geometry
826             PEDecoder pe(g_pMSCorEE);
827
828             g_runtimeLoadedBaseAddress = (SIZE_T)pe.GetBase();
829             g_runtimeVirtualSize = (SIZE_T)pe.GetVirtualSize();
830             InitCodeAllocHint(g_runtimeLoadedBaseAddress, g_runtimeVirtualSize, GetRandomInt(64));
831         }
832 #endif // !FEATURE_PAL
833
834 #endif // CROSSGEN_COMPILE
835
836         // Set up the cor handle map. This map is used to load assemblies in
837         // memory instead of using the normal system load
838         PEImage::Startup();
839
840         AccessCheckOptions::Startup();
841
842         MscorlibBinder::Startup();
843
844         Stub::Init();
845         StubLinkerCPU::Init();
846
847 #ifndef CROSSGEN_COMPILE
848
849         InitializeGarbageCollector();
850
851         // Initialize remoting
852
853         if (!GCHandleUtilities::GetGCHandleManager()->Initialize())
854         {
855             IfFailGo(E_OUTOFMEMORY);
856         }
857
858         g_pEEShutDownEvent = new CLREvent();
859         g_pEEShutDownEvent->CreateManualEvent(FALSE);
860
861         VirtualCallStubManager::InitStatic();
862
863         GCInterface::m_MemoryPressureLock.Init(CrstGCMemoryPressure);
864
865 #endif // CROSSGEN_COMPILE
866
867         // Setup the domains. Threads are started in a default domain.
868
869         // Static initialization
870         PEAssembly::Attach();
871         BaseDomain::Attach();
872         SystemDomain::Attach();
873
874         // Start up the EE intializing all the global variables
875         ECall::Init();
876
877         COMDelegate::Init();
878
879         ExecutionManager::Init();
880
881         JitHost::Init();
882
883 #ifndef CROSSGEN_COMPILE
884
885 #ifndef FEATURE_PAL      
886         if (!RegisterOutOfProcessWatsonCallbacks())
887         {
888             IfFailGo(E_FAIL);
889         }
890 #endif // !FEATURE_PAL
891
892 #ifdef DEBUGGING_SUPPORTED
893         if(!NingenEnabled())
894         {
895             // Initialize the debugging services. This must be done before any
896             // EE thread objects are created, and before any classes or
897             // modules are loaded.
898             InitializeDebugger(); // throws on error
899         }
900 #endif // DEBUGGING_SUPPORTED
901
902 #ifdef PROFILING_SUPPORTED
903         // Initialize the profiling services.
904         hr = ProfilingAPIUtility::InitializeProfiling();
905
906         _ASSERTE(SUCCEEDED(hr));
907         IfFailGo(hr);
908 #endif // PROFILING_SUPPORTED
909
910         InitializeExceptionHandling();
911
912         //
913         // Install our global exception filter
914         //
915         if (!InstallUnhandledExceptionFilter())
916         {
917             IfFailGo(E_FAIL);
918         }
919
920         // throws on error
921         SetupThread();
922
923 #ifdef DEBUGGING_SUPPORTED
924         // Notify debugger once the first thread is created to finish initialization.
925         if (g_pDebugInterface != NULL)
926         {
927             g_pDebugInterface->StartupPhase2(GetThread());
928         }
929 #endif
930
931         InitPreStubManager();
932
933 #ifdef FEATURE_COMINTEROP
934         InitializeComInterop();
935 #endif // FEATURE_COMINTEROP
936
937         StubHelpers::Init();
938
939         // Before setting up the execution manager initialize the first part
940         // of the JIT helpers.
941         InitJITHelpers1();
942         InitJITHelpers2();
943
944         SyncBlockCache::Attach();
945
946         // Set up the sync block
947         SyncBlockCache::Start();
948
949         StackwalkCache::Init();
950
951         // This isn't done as part of InitializeGarbageCollector() above because it
952         // requires write barriers to have been set up on x86, which happens as part
953         // of InitJITHelpers1.
954         hr = g_pGCHeap->Initialize();
955         IfFailGo(hr);
956
957         // This isn't done as part of InitializeGarbageCollector() above because thread
958         // creation requires AppDomains to have been set up.
959         FinalizerThread::FinalizerThreadCreate();
960
961         // Now we really have fully initialized the garbage collector
962         SetGarbageCollectorFullyInitialized();
963
964 #ifdef DEBUGGING_SUPPORTED
965         // Make a call to publish the DefaultDomain for the debugger
966         // This should be done before assemblies/modules are loaded into it (i.e. SystemDomain::Init)
967         // and after its OK to switch GC modes and syncronize for sending events to the debugger.
968         // @dbgtodo  synchronization: this can probably be simplified in V3
969         LOG((LF_CORDB | LF_SYNC | LF_STARTUP, LL_INFO1000, "EEStartup: adding default domain 0x%x\n",
970              SystemDomain::System()->DefaultDomain()));
971         SystemDomain::System()->PublishAppDomainAndInformDebugger(SystemDomain::System()->DefaultDomain());
972 #endif
973
974 #endif // CROSSGEN_COMPILE
975
976         SystemDomain::System()->Init();
977
978 #ifdef PROFILING_SUPPORTED
979         // <TODO>This is to compensate for the DefaultDomain workaround contained in
980         // SystemDomain::Attach in which the first user domain is created before profiling
981         // services can be initialized.  Profiling services cannot be moved to before the
982         // workaround because it needs SetupThread to be called.</TODO>
983
984         SystemDomain::NotifyProfilerStartup();
985 #endif // PROFILING_SUPPORTED
986
987         g_fEEInit = false;
988
989         SystemDomain::System()->DefaultDomain()->LoadSystemAssemblies();
990
991         SystemDomain::System()->DefaultDomain()->SetupSharedStatics();
992
993 #ifdef _DEBUG
994         APIThreadStress::SetThreadStressCount(g_pConfig->GetAPIThreadStressCount());
995 #endif
996 #ifdef FEATURE_STACK_SAMPLING
997         StackSampler::Init();
998 #endif
999
1000 #ifndef CROSSGEN_COMPILE
1001         if (!NingenEnabled())
1002         {
1003             // Perform any once-only SafeHandle initialization.
1004             SafeHandle::Init();
1005         }
1006
1007 #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
1008         // retrieve configured max size for the mini-metadata buffer (defaults to 64KB)
1009         g_MiniMetaDataBuffMaxSize = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MiniMdBufferCapacity);
1010         // align up to GetOsPageSize(), with a maximum of 1 MB
1011         g_MiniMetaDataBuffMaxSize = (DWORD) min(ALIGN_UP(g_MiniMetaDataBuffMaxSize, GetOsPageSize()), 1024 * 1024);
1012         // allocate the buffer. this is never touched while the process is running, so it doesn't 
1013         // contribute to the process' working set. it is needed only as a "shadow" for a mini-metadata
1014         // buffer that will be set up and reported / updated in the Watson process (the 
1015         // DacStreamsManager class coordinates this)
1016         g_MiniMetaDataBuffAddress = (TADDR) ClrVirtualAlloc(NULL, 
1017                                                 g_MiniMetaDataBuffMaxSize, MEM_COMMIT, PAGE_READWRITE);
1018 #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
1019
1020 #endif // CROSSGEN_COMPILE
1021
1022         g_fEEStarted = TRUE;
1023 #ifndef CROSSGEN_COMPILE
1024 #ifdef FEATURE_PERFTRACING
1025         DiagnosticServer::Initialize();
1026 #endif
1027 #endif
1028         g_EEStartupStatus = S_OK;
1029         hr = S_OK;
1030         STRESS_LOG0(LF_STARTUP, LL_ALWAYS, "===================EEStartup Completed===================");
1031
1032 #ifndef CROSSGEN_COMPILE
1033
1034 #ifdef _DEBUG
1035
1036         //if g_fEEStarted was false when we loaded the System Module, we did not run ExpandAll on it.  In
1037         //this case, make sure we run ExpandAll here.  The rationale is that if we Jit before g_fEEStarted
1038         //is true, we can't initialize Com, so we can't jit anything that uses Com types.  Also, it's
1039         //probably not safe to Jit while g_fEEStarted is false.
1040         //
1041         //Also, if you run this it's possible we'll call CoInitialize, which defaults to MTA.  This might
1042         //mess up an application that uses STA.  However, this mode is only supported for certain limited
1043         //jit testing scenarios, so it can live with the limitation.
1044         if (g_pConfig->ExpandModulesOnLoad())
1045         {
1046             SystemDomain::SystemModule()->ExpandAll();
1047         }
1048
1049         // Perform mscorlib consistency check if requested
1050         g_Mscorlib.CheckExtended();
1051
1052 #endif // _DEBUG
1053
1054 #ifdef HAVE_GCCOVER
1055         MethodDesc::Init();
1056 #endif
1057
1058 #endif // !CROSSGEN_COMPILE
1059
1060 ErrExit: ;
1061     }
1062     EX_CATCH
1063     {
1064 #ifdef CROSSGEN_COMPILE
1065         // for minimal impact we won't update hr for regular builds
1066         hr = GET_EXCEPTION()->GetHR();
1067         _ASSERTE(FAILED(hr));
1068         StackSString exceptionMessage;
1069         GET_EXCEPTION()->GetMessage(exceptionMessage);
1070         fprintf(stderr, "%S\n", exceptionMessage.GetUnicode());
1071 #endif // CROSSGEN_COMPILE
1072     }
1073     EX_END_CATCH(RethrowTerminalExceptionsWithInitCheck)
1074
1075     if (!g_fEEStarted) {
1076         if (g_fEEInit)
1077             g_fEEInit = false;
1078
1079         if (!FAILED(hr))
1080             hr = E_FAIL;
1081
1082         g_EEStartupStatus = hr;
1083     }
1084
1085     if (breakOnEELoad.val(CLRConfig::UNSUPPORTED_BreakOnEELoad) == 2)
1086     {
1087 #ifdef _DEBUG
1088         _ASSERTE(!"Done loading EE!");
1089 #else
1090         DebugBreak();
1091 #endif
1092     }
1093
1094 }
1095
1096 LONG FilterStartupException(PEXCEPTION_POINTERS p, PVOID pv)
1097 {
1098     CONTRACTL
1099     {
1100         NOTHROW;
1101         GC_NOTRIGGER;
1102         MODE_ANY;
1103         PRECONDITION(CheckPointer(p));
1104         PRECONDITION(CheckPointer(pv));
1105     } CONTRACTL_END;
1106
1107     g_EEStartupStatus = (HRESULT)p->ExceptionRecord->ExceptionInformation[0];
1108
1109     // Make sure we got a failure code in this case
1110     if (!FAILED(g_EEStartupStatus))
1111         g_EEStartupStatus = E_FAIL;
1112
1113     // Initializations has failed so reset the g_fEEInit flag.
1114     g_fEEInit = false;
1115
1116     if (p->ExceptionRecord->ExceptionCode == BOOTUP_EXCEPTION_COMPLUS)
1117     {
1118         // Don't ever handle the exception in a checked build
1119 #ifndef _DEBUG
1120         return EXCEPTION_EXECUTE_HANDLER;
1121 #endif
1122     }
1123
1124     return EXCEPTION_CONTINUE_SEARCH;
1125 }
1126
1127 // EEStartup is responsible for all the one time intialization of the runtime.  Some of the highlights of
1128 // what it does include
1129 //     * Creates the default and shared, appdomains. 
1130 //     * Loads mscorlib.dll and loads up the fundamental types (System.Object ...)
1131 // 
1132 // see code:EEStartup#TableOfContents for more on the runtime in general. 
1133 // see code:#EEShutdown for a analagous routine run during shutdown. 
1134 // 
1135 HRESULT EEStartup(COINITIEE fFlags)
1136 {
1137     // Cannot use normal contracts here because of the PAL_TRY.
1138     STATIC_CONTRACT_NOTHROW;
1139
1140     _ASSERTE(!g_fEEStarted && !g_fEEInit && SUCCEEDED (g_EEStartupStatus));
1141
1142     PAL_TRY(COINITIEE *, pfFlags, &fFlags)
1143     {
1144 #ifndef CROSSGEN_COMPILE
1145         InitializeClrNotifications();
1146 #ifdef FEATURE_PAL
1147         InitializeJITNotificationTable();
1148         DacGlobals::Initialize();
1149 #endif
1150 #endif // CROSSGEN_COMPILE
1151
1152         EEStartupHelper(*pfFlags);
1153     }
1154     PAL_EXCEPT_FILTER (FilterStartupException)
1155     {
1156         // The filter should have set g_EEStartupStatus to a failure HRESULT.
1157         _ASSERTE(FAILED(g_EEStartupStatus));
1158     }
1159     PAL_ENDTRY
1160
1161     return g_EEStartupStatus;
1162 }
1163
1164
1165 #ifndef CROSSGEN_COMPILE
1166
1167 #ifdef FEATURE_COMINTEROP
1168
1169 void InnerCoEEShutDownCOM()
1170 {
1171     CONTRACTL
1172     {
1173         THROWS;
1174         GC_TRIGGERS;
1175         MODE_ANY;
1176     } CONTRACTL_END;
1177
1178     static LONG AlreadyDone = -1;
1179
1180     if (g_fEEStarted != TRUE)
1181         return;
1182
1183     if (FastInterlockIncrement(&AlreadyDone) != 0)
1184         return;
1185
1186     g_fShutDownCOM = true;
1187
1188     // Release IJupiterGCMgr *
1189     RCWWalker::OnEEShutdown();
1190
1191     // Release all of the RCWs in all contexts in all caches.
1192     ReleaseRCWsInCaches(NULL);
1193
1194 #ifdef FEATURE_APPX    
1195     // Cleanup cached factory pointer in SynchronizationContextNative
1196     SynchronizationContextNative::Cleanup();
1197 #endif    
1198 }
1199
1200 #endif // FEATURE_COMINTEROP
1201
1202 // ---------------------------------------------------------------------------
1203 // %%Function: ForceEEShutdown()
1204 //
1205 // Description: Force the EE to shutdown now.
1206 // 
1207 // Note: returns when sca is SCA_ReturnWhenShutdownComplete.
1208 // ---------------------------------------------------------------------------
1209 void ForceEEShutdown(ShutdownCompleteAction sca)
1210 {
1211     WRAPPER_NO_CONTRACT;
1212
1213     // Don't bother to take the lock for this case.
1214
1215     STRESS_LOG0(LF_STARTUP, INFO3, "EEShutdown invoked from ForceEEShutdown");
1216     EEPolicy::HandleExitProcess(sca);
1217 }
1218
1219 static bool WaitForEndOfShutdown_OneIteration()
1220 {
1221     CONTRACTL{
1222         NOTHROW;
1223         GC_NOTRIGGER;
1224         MODE_PREEMPTIVE;
1225     } CONTRACTL_END;
1226
1227     // We are shutting down.  GC triggers does not have any effect now.
1228     CONTRACT_VIOLATION(GCViolation);
1229
1230     // If someone calls EEShutDown while holding OS loader lock, the thread we created for shutdown
1231     // won't start running.  This is a deadlock we can not fix.  Instead, we timeout and continue the 
1232     // current thread.
1233     DWORD timeout = GetEEPolicy()->GetTimeout(OPR_ProcessExit);
1234     timeout *= 2;
1235     ULONGLONG endTime = CLRGetTickCount64() + timeout;
1236     bool done = false;
1237
1238     EX_TRY
1239     {
1240         ULONGLONG curTime = CLRGetTickCount64();
1241         if (curTime > endTime)
1242         {
1243             done = true;
1244         }
1245         else
1246         {
1247 #ifdef PROFILING_SUPPORTED
1248             if (CORProfilerPresent())
1249             {
1250                 // A profiler is loaded, so just wait without timeout. This allows
1251                 // profilers to complete potentially lengthy post processing, without the
1252                 // CLR killing them off first. The Office team's server memory profiler,
1253                 // for example, does a lot of post-processing that can exceed the 80
1254                 // second imit we normally impose here. The risk of waiting without
1255                 // timeout is that, if there really is a deadlock, shutdown will hang.
1256                 // Since that will only happen if a profiler is loaded, that is a
1257                 // reasonable compromise
1258                 timeout = INFINITE;
1259             }
1260             else
1261 #endif //PROFILING_SUPPORTED
1262             {
1263                 timeout = static_cast<DWORD>(endTime - curTime);
1264             }
1265             DWORD status = g_pEEShutDownEvent->Wait(timeout,TRUE);
1266             if (status == WAIT_OBJECT_0 || status == WAIT_TIMEOUT)
1267             {
1268                 done = true;
1269             }
1270             else
1271             {
1272                 done = false;
1273             }
1274         }
1275     }
1276     EX_CATCH
1277     {
1278     }
1279     EX_END_CATCH(SwallowAllExceptions);
1280     return done;
1281 }
1282
1283 void WaitForEndOfShutdown()
1284 {
1285     CONTRACTL{
1286         NOTHROW;
1287         GC_NOTRIGGER;
1288         MODE_PREEMPTIVE;
1289     } CONTRACTL_END;
1290
1291     // We are shutting down.  GC triggers does not have any effect now.
1292     CONTRACT_VIOLATION(GCViolation);
1293
1294     Thread *pThread = GetThread();
1295     // After a thread is blocked in WaitForEndOfShutdown, the thread should not enter runtime again,
1296     // and block at WaitForEndOfShutdown again.
1297     if (pThread)
1298     {
1299         _ASSERTE(!pThread->HasThreadStateNC(Thread::TSNC_BlockedForShutdown));
1300         pThread->SetThreadStateNC(Thread::TSNC_BlockedForShutdown);
1301     }
1302
1303     while (!WaitForEndOfShutdown_OneIteration());
1304 }
1305
1306 // ---------------------------------------------------------------------------
1307 // Function: EEShutDownHelper(BOOL fIsDllUnloading)
1308 //
1309 // The real meat of shut down happens here.  See code:#EEShutDown for details, including
1310 // what fIsDllUnloading means.
1311 //
1312 void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading)
1313 {
1314     CONTRACTL
1315     {
1316         NOTHROW;
1317         GC_TRIGGERS;
1318         MODE_ANY;
1319     } CONTRACTL_END;
1320
1321     // Used later for a callback.
1322     CEEInfo ceeInf;
1323
1324     if (fIsDllUnloading)
1325     {
1326         // The process is detaching, so set the global state.
1327         // This is used to get around FreeLibrary problems.
1328         g_fProcessDetach = true;
1329
1330         ETW::EnumerationLog::ProcessShutdown();
1331     }
1332
1333 #ifdef FEATURE_PERFTRACING
1334     if (!fIsDllUnloading)
1335     {
1336         EventPipe::Shutdown();
1337         DiagnosticServer::Shutdown();
1338     }
1339 #endif // FEATURE_PERFTRACING
1340
1341 #if defined(FEATURE_COMINTEROP)
1342     // Get the current thread.
1343     Thread * pThisThread = GetThread();
1344 #endif
1345
1346     if (IsDbgHelperSpecialThread())
1347     {
1348         // Our debugger helper thread does not allow Thread object to be set up.
1349         // We should not run shutdown code on debugger helper thread.
1350         _ASSERTE(fIsDllUnloading);
1351         return;
1352     }
1353
1354 #ifdef _DEBUG
1355     // stop API thread stress
1356     APIThreadStress::SetThreadStressCount(0);
1357 #endif
1358
1359     STRESS_LOG1(LF_STARTUP, LL_INFO10, "EEShutDown entered unloading = %d", fIsDllUnloading);
1360
1361 #ifdef _DEBUG
1362     if (_DbgBreakCount)
1363         _ASSERTE(!"An assert was hit before EE Shutting down");
1364
1365     if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_BreakOnEEShutdown))
1366         _ASSERTE(!"Shutting down EE!");
1367 #endif
1368
1369 #ifdef DEBUGGING_SUPPORTED
1370     // This is a nasty, terrible, horrible thing. If we're being
1371     // called from our DLL main, then the odds are good that our DLL
1372     // main has been called as the result of some person calling
1373     // ExitProcess. That rips the debugger helper thread away very
1374     // ungracefully. This check is an attempt to recognize that case
1375     // and avoid the impending hang when attempting to get the helper
1376     // thread to do things for us.
1377     if ((g_pDebugInterface != NULL) && g_fProcessDetach)
1378         g_pDebugInterface->EarlyHelperThreadDeath();
1379 #endif // DEBUGGING_SUPPORTED
1380
1381     EX_TRY
1382     {
1383         ClrFlsSetThreadType(ThreadType_Shutdown);
1384
1385         if (fIsDllUnloading && g_fEEShutDown)
1386         {
1387             // I'm in the final shutdown and the first part has already been run.
1388             goto part2;
1389         }
1390
1391         // Indicate the EE is the shut down phase.
1392         g_fEEShutDown |= ShutDown_Start;
1393
1394         // Terminate the BBSweep thread
1395         g_BBSweep.ShutdownBBSweepThread();
1396
1397         if (!g_fProcessDetach && !g_fFastExitProcess)
1398         {
1399             g_fEEShutDown |= ShutDown_Finalize1;
1400
1401             // Wait for the finalizer thread to deliver process exit event
1402             GCX_PREEMP();
1403             FinalizerThread::RaiseShutdownEvents();
1404         }
1405
1406         // Ok.  Let's stop the EE.
1407         if (!g_fProcessDetach)
1408         {
1409             // Convert key locks into "shutdown" mode. A lock in shutdown mode means:
1410             // - Only the finalizer/helper/shutdown threads will be able to take the the lock.
1411             // - Any other thread that tries takes it will just get redirected to an endless WaitForEndOfShutdown().
1412             //
1413             // The only managed code that should run after this point is the finalizers for shutdown.
1414             // We convert locks needed for running + debugging such finalizers. Since such locks may need to be
1415             // juggled between multiple threads (finalizer/helper/shutdown), no single thread can take the
1416             // lock and not give it up.
1417             //
1418             // Each lock needs its own shutdown flag (they can't all be converted at once).
1419             // To avoid deadlocks, we need to convert locks in order of crst level (biggest first).
1420
1421             // Notify the debugger that we're going into shutdown to convert debugger-lock to shutdown.
1422             if (g_pDebugInterface != NULL)
1423             {
1424                 g_pDebugInterface->LockDebuggerForShutdown();
1425             }
1426
1427             // This call will convert the ThreadStoreLock into "shutdown" mode, just like the debugger lock above.
1428             g_fEEShutDown |= ShutDown_Finalize2;
1429         }
1430
1431 #ifdef FEATURE_EVENT_TRACE
1432         // Flush managed object allocation logging data.
1433         // We do this after finalization is complete and returning threads have been trapped, so that
1434         // no there will be no more managed allocations and no more GCs which will manipulate the
1435         // allocation sampling data structures.
1436         ETW::TypeSystemLog::FlushObjectAllocationEvents();
1437 #endif // FEATURE_EVENT_TRACE
1438
1439 #ifdef FEATURE_PERFMAP
1440         // Flush and close the perf map file.
1441         PerfMap::Destroy();
1442 #endif
1443
1444         {
1445             // If we're doing basic block profiling, we need to write the log files to disk.
1446             static BOOL fIBCLoggingDone = FALSE;
1447             if (!fIBCLoggingDone)
1448             {
1449                 if (g_IBCLogger.InstrEnabled())
1450                 {
1451                     Thread * pThread = GetThread();
1452                     ThreadLocalIBCInfo* pInfo = pThread->GetIBCInfo();
1453
1454                     // Acquire the Crst lock before creating the IBCLoggingDisabler object.
1455                     // Only one thread at a time can be processing an IBC logging event.
1456                     CrstHolder lock(IBCLogger::GetSync());
1457                     {
1458                         IBCLoggingDisabler disableLogging( pInfo );  // runs IBCLoggingDisabler::DisableLogging
1459                         
1460                         CONTRACT_VIOLATION(GCViolation);
1461                         Module::WriteAllModuleProfileData(true);
1462                     }
1463                 }
1464                 fIBCLoggingDone = TRUE;
1465             }
1466         }
1467
1468         ceeInf.JitProcessShutdownWork();  // Do anything JIT-related that needs to happen at shutdown.
1469
1470 #ifdef FEATURE_INTERPRETER
1471         // This will check a flag and do nothing if not enabled.
1472         Interpreter::PrintPostMortemData();
1473 #endif // FEATURE_INTERPRETER
1474         
1475 #ifdef PROFILING_SUPPORTED
1476         // If profiling is enabled, then notify of shutdown first so that the
1477         // profiler can make any last calls it needs to.  Do this only if we
1478         // are not detaching
1479
1480         // NOTE: We haven't stopped other threads at this point and nothing is stopping
1481         // callbacks from coming into the profiler even after Shutdown() has been called.
1482         // See https://github.com/dotnet/coreclr/issues/22176 for an example of how that
1483         // happens.
1484         //
1485         // To prevent issues when profilers are attached we intentionally skip freeing the
1486         // profiler here. Since there is no guarantee that the profiler won't be accessed after
1487         // we free it (e.g. through callbacks or ELT hooks), we can't safely free the profiler.
1488         if (CORProfilerPresent())
1489         {
1490             // Don't call back in to the profiler if we are being torn down, it might be unloaded
1491             if (!fIsDllUnloading)
1492             {
1493                 BEGIN_PIN_PROFILER(CORProfilerPresent());
1494                 GCX_PREEMP();
1495                 g_profControlBlock.pProfInterface->Shutdown();
1496                 END_PIN_PROFILER();
1497             }
1498
1499             g_fEEShutDown |= ShutDown_Profiler;
1500         }
1501 #endif // PROFILING_SUPPORTED
1502
1503
1504 #ifdef _DEBUG
1505         g_fEEShutDown |= ShutDown_SyncBlock;
1506 #endif
1507         {
1508             // From here on out we might call stuff that violates mode requirements, but we ignore these
1509             // because we are shutting down.
1510             CONTRACT_VIOLATION(ModeViolation);
1511
1512 #ifdef FEATURE_COMINTEROP
1513             // We need to call CoUninitialize in part one to ensure orderly shutdown of COM dlls.
1514             if (!g_fFastExitProcess)
1515             {
1516                 if (pThisThread!= NULL)
1517                 {
1518                     pThisThread->CoUninitialize();
1519                 }
1520             }
1521 #endif // FEATURE_COMINTEROP
1522         }
1523
1524         // This is the end of Part 1.
1525
1526 part2:
1527         // If process shutdown is in progress and Crst locks to be used in shutdown phase 2
1528         // are already in use, then skip phase 2. This will happen only when those locks
1529         // are orphaned. In Vista, the penalty for attempting to enter such locks is 
1530         // instant process termination.
1531         if (g_fProcessDetach)
1532         {
1533             // The assert below is a bit too aggresive and has generally brought cases that have been race conditions
1534             // and not easily reproed to validate a bug. A typical race scenario is when there are two threads,
1535             // T1 and T2, with T2 having taken a lock (e.g. SystemDomain lock), the OS terminates
1536             // T2 for some reason. Later, when we enter the shutdown thread, we would assert on such
1537             // a lock leak, but there is not much we can do since the OS wont notify us prior to thread 
1538             // termination. And this is not even a user bug.
1539             //
1540             // Converting it to a STRESS LOG to reduce noise, yet keep things in radar if they need
1541             // to be investigated.
1542             //_ASSERTE_MSG(g_ShutdownCrstUsageCount == 0, "Some locks to be taken during shutdown may already be orphaned!");
1543             if (g_ShutdownCrstUsageCount > 0)
1544             {
1545                 STRESS_LOG0(LF_STARTUP, LL_INFO10, "Some locks to be taken during shutdown may already be orphaned!");
1546                 goto lDone;
1547             }
1548         }
1549
1550         {
1551             CONTRACT_VIOLATION(ModeViolation);
1552
1553             // On the new plan, we only do the tear-down under the protection of the loader
1554             // lock -- after the OS has stopped all other threads.
1555             if (fIsDllUnloading && (g_fEEShutDown & ShutDown_Phase2) == 0)
1556             {
1557                 g_fEEShutDown |= ShutDown_Phase2;
1558
1559                 // Shutdown finalizer before we suspend all background threads. Otherwise we
1560                 // never get to finalize anything. Obviously.
1561
1562 #ifdef _DEBUG
1563                 if (_DbgBreakCount)
1564                     _ASSERTE(!"An assert was hit After Finalizer run");
1565 #endif
1566
1567                 // No longer process exceptions
1568                 g_fNoExceptions = true;
1569
1570                 //
1571                 // Remove our global exception filter. If it was NULL before, we want it to be null now.
1572                 //
1573                 UninstallUnhandledExceptionFilter();
1574
1575                 // <TODO>@TODO: This does things which shouldn't occur in part 2.  Namely,
1576                 // calling managed dll main callbacks (AppDomain::SignalProcessDetach), and
1577                 // RemoveAppDomainFromIPC.
1578                 //
1579                 // (If we move those things to earlier, this can be called only if fShouldWeCleanup.)</TODO>
1580                 if (!g_fFastExitProcess)
1581                 {
1582                     SystemDomain::DetachBegin();
1583                 }
1584
1585
1586 #ifdef DEBUGGING_SUPPORTED
1587                 // Terminate the debugging services.
1588                 TerminateDebugger();
1589 #endif // DEBUGGING_SUPPORTED
1590
1591                 StubManager::TerminateStubManagers();
1592
1593 #ifdef FEATURE_INTERPRETER
1594                 Interpreter::Terminate();
1595 #endif // FEATURE_INTERPRETER
1596
1597                 //@TODO: find the right place for this
1598                 VirtualCallStubManager::UninitStatic();
1599
1600 #ifdef ENABLE_PERF_LOG
1601                 PerfLog::PerfLogDone();
1602 #endif //ENABLE_PERF_LOG
1603
1604                 // Unregister our vectored exception and continue handlers from the OS.
1605                 // This will ensure that if any other DLL unload (after ours) has an exception,
1606                 // we wont attempt to process that exception (which could lead to various
1607                 // issues including AV in the runtime).
1608                 //
1609                 // This should be done:
1610                 //
1611                 // 1) As the last action during the shutdown so that any unexpected AVs
1612                 //    in the runtime during shutdown do result in FailFast in VEH.
1613                 //
1614                 // 2) Only when the runtime is processing DLL_PROCESS_DETACH. 
1615                 CLRRemoveVectoredHandlers();
1616
1617 #if USE_DISASSEMBLER
1618                 Disassembler::StaticClose();
1619 #endif // USE_DISASSEMBLER
1620
1621 #ifdef _DEBUG
1622                 if (_DbgBreakCount)
1623                     _ASSERTE(!"EE Shutting down after an assert");
1624 #endif
1625
1626
1627 #ifdef LOGGING
1628                 extern unsigned FcallTimeHist[11];
1629 #endif
1630                 LOG((LF_STUBS, LL_INFO10, "FcallHist %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
1631                     FcallTimeHist[0], FcallTimeHist[1], FcallTimeHist[2], FcallTimeHist[3],
1632                     FcallTimeHist[4], FcallTimeHist[5], FcallTimeHist[6], FcallTimeHist[7],
1633                     FcallTimeHist[8], FcallTimeHist[9], FcallTimeHist[10]));
1634
1635                 WriteJitHelperCountToSTRESSLOG();
1636
1637                 STRESS_LOG0(LF_STARTUP, LL_INFO10, "EEShutdown shutting down logging");
1638
1639 #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
1640                 if (!g_fFastExitProcess)
1641                     StressLog::Terminate(TRUE);
1642 #endif
1643
1644 #ifdef LOGGING
1645                 ShutdownLogging();
1646 #endif
1647             }
1648         }    
1649
1650     lDone: ;
1651     }
1652     EX_CATCH
1653     {
1654     }
1655     EX_END_CATCH(SwallowAllExceptions);
1656
1657     ClrFlsClearThreadType(ThreadType_Shutdown);
1658     if (!g_fProcessDetach)
1659     {
1660         g_pEEShutDownEvent->Set();
1661     }
1662 }
1663
1664
1665 #ifdef FEATURE_COMINTEROP
1666
1667 BOOL IsThreadInSTA()
1668 {
1669     CONTRACTL
1670     {
1671         NOTHROW;
1672         GC_TRIGGERS;
1673         MODE_ANY;
1674     }
1675     CONTRACTL_END;
1676
1677     // If ole32.dll is not loaded
1678     if (WszGetModuleHandle(W("ole32.dll")) == NULL)
1679     {
1680         return FALSE;
1681     }
1682
1683     BOOL fInSTA = TRUE;
1684     // To be conservative, check if finalizer thread is around
1685     EX_TRY
1686     {
1687         Thread *pFinalizerThread = FinalizerThread::GetFinalizerThread();
1688         if (!pFinalizerThread || pFinalizerThread->Join(0, FALSE) != WAIT_TIMEOUT)
1689         {
1690             fInSTA = FALSE;
1691         }
1692     }
1693     EX_CATCH
1694     {
1695     }
1696     EX_END_CATCH(SwallowAllExceptions);
1697
1698     if (!fInSTA)
1699     {
1700         return FALSE;
1701     }
1702
1703     THDTYPE type;
1704     HRESULT hr = S_OK;
1705
1706     hr = GetCurrentThreadTypeNT5(&type);
1707     if (hr == S_OK)
1708     {
1709         fInSTA = (type == THDTYPE_PROCESSMESSAGES) ? TRUE : FALSE;
1710
1711         // If we get back THDTYPE_PROCESSMESSAGES, we are guaranteed to
1712         // be an STA thread. If not, we are an MTA thread, however
1713         // we can't know if the thread has been explicitly set to MTA
1714         // (via a call to CoInitializeEx) or if it has been implicitly
1715         // made MTA (if it hasn't been CoInitializeEx'd but CoInitialize
1716         // has already been called on some other thread in the process.
1717     }
1718     else
1719     {
1720         // CoInitialize hasn't been called in the process yet so assume the current thread
1721         // is MTA. 
1722         fInSTA = FALSE;
1723     }
1724
1725     return fInSTA;
1726 }
1727 #endif
1728
1729 // #EEShutDown
1730 // 
1731 // Function: EEShutDown(BOOL fIsDllUnloading)
1732 //
1733 // Parameters:
1734 //    BOOL fIsDllUnloading:
1735 //         * TRUE => Called from CLR's DllMain (DLL_PROCESS_DETACH). Not safe point for
1736 //             full cleanup
1737 //         * FALSE => Called some other way (e.g., end of the CLR's main). Safe to do
1738 //             full cleanup.
1739 //
1740 // Description:
1741 // 
1742 //     All ee shutdown stuff should be done here. EEShutDown is generally called in one
1743 //     of two ways:
1744 //     * 1. From code:EEPolicy::HandleExitProcess (via HandleExitProcessHelper), with
1745 //         fIsDllUnloading == FALSE. This code path is typically invoked by the CLR's
1746 //         main just falling through to the end. Full cleanup can be performed when
1747 //         EEShutDown is called this way.
1748 //     * 2. From CLR's DllMain (DLL_PROCESS_DETACH), with fIsDllUnloading == TRUE. When
1749 //         called this way, much cleanup code is unsafe to run, and is thus skipped.
1750 // 
1751 // Actual shut down logic is factored out to EEShutDownHelper which may be called
1752 // directly by EEShutDown, or indirectly on another thread (see code:#STAShutDown).
1753 //
1754 // In order that callees may also know the value of fIsDllUnloading, EEShutDownHelper
1755 // sets g_fProcessDetach = fIsDllUnloading, and g_fProcessDetach may then be retrieved
1756 // via code:IsAtProcessExit.
1757 //
1758 // NOTE 1: Actually, g_fProcessDetach is set to TRUE if fIsDllUnloading is TRUE. But
1759 // g_fProcessDetach doesn't appear to be explicitly set to FALSE. (Apparently
1760 // g_fProcessDetach is implicitly initialized to FALSE as clr.dll is loaded.)
1761 // 
1762 // NOTE 2: EEDllMain(DLL_PROCESS_DETACH) already sets g_fProcessDetach to TRUE, so it
1763 // appears EEShutDownHelper doesn't have to.
1764 // 
1765 void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading)
1766 {
1767     CONTRACTL {
1768         NOTHROW;
1769         GC_TRIGGERS;
1770         MODE_ANY;
1771         PRECONDITION(g_fEEStarted);
1772     } CONTRACTL_END;
1773
1774     // If we have not started runtime successfully, it is not safe to call EEShutDown.
1775     if (!g_fEEStarted || g_fFastExitProcess == 2)
1776     {
1777         return;
1778     }
1779
1780     // We only do the first part of the shutdown once.
1781     static LONG OnlyOne = -1;
1782
1783     if (!fIsDllUnloading)
1784     {
1785         if (FastInterlockIncrement(&OnlyOne) != 0)
1786         {
1787             // I'm in a regular shutdown -- but another thread got here first.
1788             // It's a race if I return from here -- I'll call ExitProcess next, and
1789             // rip things down while the first thread is half-way through a
1790             // nice cleanup.  Rather than do that, I should just wait until the
1791             // first thread calls ExitProcess().  I'll die a nice death when that
1792             // happens.
1793             GCX_PREEMP_NO_DTOR();
1794             WaitForEndOfShutdown();
1795             return;
1796         }
1797
1798 #ifdef FEATURE_MULTICOREJIT
1799         if (!AppX::IsAppXProcess()) // When running as Appx, make the delayed timer driven writing be the only option
1800         {
1801             MulticoreJitManager::StopProfileAll();
1802         }
1803 #endif
1804     }
1805
1806     if (GetThread())
1807     {
1808         GCX_COOP();
1809         EEShutDownHelper(fIsDllUnloading);
1810     }
1811     else
1812     {
1813         EEShutDownHelper(fIsDllUnloading);
1814     }
1815 }
1816
1817 // ---------------------------------------------------------------------------
1818 // %%Function: IsRuntimeActive()
1819 //
1820 // Parameters:
1821 //  none
1822 //
1823 // Returns:
1824 //  TRUE or FALSE
1825 //
1826 // Description: Indicates if the runtime is active or not. "Active" implies
1827 //              that the runtime has started and is in a position to run
1828 //              managed code.
1829 // ---------------------------------------------------------------------------
1830 BOOL IsRuntimeActive()
1831 {
1832     return (g_fEEStarted);
1833 }
1834
1835 //*****************************************************************************
1836 BOOL ExecuteDLL_ReturnOrThrow(HRESULT hr, BOOL fFromThunk)
1837 {
1838     CONTRACTL {
1839         if (fFromThunk) THROWS; else NOTHROW;
1840         WRAPPER(GC_TRIGGERS);
1841         MODE_ANY;
1842     } CONTRACTL_END;
1843
1844     // If we have a failure result, and we're called from a thunk,
1845     // then we need to throw an exception to communicate the error.
1846     if (FAILED(hr) && fFromThunk)
1847     {
1848         COMPlusThrowHR(hr);
1849     }
1850     return SUCCEEDED(hr);
1851 }
1852
1853 //
1854 // Initialize the Garbage Collector
1855 //
1856
1857 void InitializeGarbageCollector()
1858 {
1859     CONTRACTL{
1860         THROWS;
1861         GC_TRIGGERS;
1862         MODE_ANY;
1863     } CONTRACTL_END;
1864
1865     HRESULT hr;
1866
1867     // Build the special Free Object used by the Generational GC
1868     _ASSERT(g_pFreeObjectMethodTable == NULL);
1869     g_pFreeObjectMethodTable = (MethodTable *) new BYTE[sizeof(MethodTable)];
1870     ZeroMemory(g_pFreeObjectMethodTable, sizeof(MethodTable));
1871
1872     // As the flags in the method table indicate there are no pointers
1873     // in the object, there is no gc descriptor, and thus no need to adjust
1874     // the pointer to skip the gc descriptor.
1875
1876     g_pFreeObjectMethodTable->SetBaseSize(ARRAYBASE_BASESIZE);
1877     g_pFreeObjectMethodTable->SetComponentSize(1);
1878
1879     hr = GCHeapUtilities::LoadAndInitialize();
1880     if (hr != S_OK)
1881     {
1882         ThrowHR(hr);
1883     }
1884
1885     // Apparently the Windows linker removes global variables if they are never
1886     // read from, which is a problem for g_gcDacGlobals since it's expected that
1887     // only the DAC will read from it. This forces the linker to include
1888     // g_gcDacGlobals.
1889     volatile void* _dummy = g_gcDacGlobals;
1890 }
1891
1892 /*****************************************************************************/
1893 /* This is here only so that if we get an exception we stop before we catch it */
1894 LONG DllMainFilter(PEXCEPTION_POINTERS p, PVOID pv)
1895 {
1896     LIMITED_METHOD_CONTRACT;
1897     _ASSERTE(!"Exception happened in mscorwks!DllMain!");
1898     return EXCEPTION_EXECUTE_HANDLER;
1899 }
1900
1901 //*****************************************************************************
1902 // This is the part of the old-style DllMain that initializes the
1903 // stuff that the EE team works on. It's called from the real DllMain
1904 // up in MSCOREE land. Separating the DllMain tasks is simply for
1905 // convenience due to the dual build trees.
1906 //*****************************************************************************
1907 BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error.
1908     HINSTANCE   hInst,             // Instance handle of the loaded module.
1909     DWORD       dwReason,          // Reason for loading.
1910     LPVOID      lpReserved)        // Unused.
1911 {
1912     STATIC_CONTRACT_NOTHROW;
1913     STATIC_CONTRACT_GC_TRIGGERS;
1914
1915     // HRESULT hr;
1916     // BEGIN_EXTERNAL_ENTRYPOINT(&hr);
1917     // EE isn't spun up enough to use this macro
1918
1919     struct Param
1920     {
1921         HINSTANCE hInst;
1922         DWORD dwReason;
1923         LPVOID lpReserved;
1924         void **pTlsData;
1925     } param;
1926     param.hInst = hInst;
1927     param.dwReason = dwReason;
1928     param.lpReserved = lpReserved;
1929     param.pTlsData = NULL;
1930
1931     // Can't use PAL_TRY/EX_TRY here as they access the ClrDebugState which gets blown away as part of the
1932     // PROCESS_DETACH path. Must use special PAL_TRY_FOR_DLLMAIN, passing the reason were in the DllMain.
1933     PAL_TRY_FOR_DLLMAIN(Param *, pParam, &param, pParam->dwReason)
1934     {
1935
1936     switch (pParam->dwReason)
1937         {
1938             case DLL_PROCESS_ATTACH:
1939             {
1940                 // We cache the SystemInfo for anyone to use throughout the
1941                 // life of the DLL.
1942                 GetSystemInfo(&g_SystemInfo);
1943
1944                 // Remember module instance
1945                 g_pMSCorEE = pParam->hInst;
1946
1947
1948                 // Set callbacks so that LoadStringRC knows which language our
1949                 // threads are in so that it can return the proper localized string.
1950             // TODO: This shouldn't rely on the LCID (id), but only the name
1951                 SetResourceCultureCallbacks(GetThreadUICultureNames,
1952                                             GetThreadUICultureId);
1953
1954                 InitEEPolicy();
1955
1956                 break;
1957             }
1958
1959             case DLL_PROCESS_DETACH:
1960             {
1961                 // lpReserved is NULL if we're here because someone called FreeLibrary
1962                 // and non-null if we're here because the process is exiting.
1963                 // Since nobody should ever be calling FreeLibrary on mscorwks.dll, lpReserved
1964                 // should always be non NULL.
1965                 _ASSERTE(pParam->lpReserved || !g_fEEStarted);
1966                 g_fProcessDetach = TRUE;
1967
1968                 if (g_fEEStarted)
1969                 {
1970                     if (GCHeapUtilities::IsGCInProgress())
1971                     {
1972                         g_fEEShutDown |= ShutDown_Phase2;
1973                         break;
1974                     }
1975
1976                     LOG((LF_STARTUP, INFO3, "EEShutDown invoked from EEDllMain"));
1977                     EEShutDown(TRUE); // shut down EE if it was started up
1978                 }
1979                 else
1980                 {
1981                     CLRRemoveVectoredHandlers();
1982                 }
1983                 break;
1984             }
1985
1986             case DLL_THREAD_DETACH:
1987             {
1988                 // Don't destroy threads here if we're in shutdown (shutdown will
1989                 // clean up for us instead).
1990
1991                 // Store the TLS data; we'll need it later and we might NULL the slot in DetachThread.
1992                 // This would be problematic because we can't depend on the FLS still existing.
1993                 pParam->pTlsData = CExecutionEngine::CheckThreadStateNoCreate(0
1994 #ifdef _DEBUG
1995                  // When we get here, OS has destroyed FLS, so FlsGetValue returns NULL now.
1996                  // We have validation code in CExecutionEngine::CheckThreadStateNoCreate to ensure that
1997                  // our TLS and FLS data are consistent, but since FLS has been destroyed, we need
1998                  // to silent the check there.  The extra arg for check build is for this purpose.
1999                                                                                          , TRUE
2000 #endif
2001                                                                                          );
2002                 Thread* thread = GetThread();
2003                 if (thread)
2004                 {
2005 #ifdef FEATURE_COMINTEROP
2006                     // reset the CoInitialize state
2007                     // so we don't call CoUninitialize during thread detach
2008                     thread->ResetCoInitialized();
2009 #endif // FEATURE_COMINTEROP
2010                     // For case where thread calls ExitThread directly, we need to reset the
2011                     // frame pointer. Otherwise stackwalk would AV. We need to do it in cooperative mode.
2012                     // We need to set m_GCOnTransitionsOK so this thread won't trigger GC when toggle GC mode
2013                     if (thread->m_pFrame != FRAME_TOP)
2014                     {
2015 #ifdef _DEBUG
2016                         thread->m_GCOnTransitionsOK = FALSE;
2017 #endif
2018                         GCX_COOP_NO_DTOR();
2019                         thread->m_pFrame = FRAME_TOP;
2020                         GCX_COOP_NO_DTOR_END();
2021                     }
2022                     thread->DetachThread(TRUE);
2023                 }
2024             }
2025         }
2026
2027     }
2028     PAL_EXCEPT_FILTER(DllMainFilter)
2029     {
2030     }
2031     PAL_ENDTRY;
2032
2033     if (dwReason == DLL_THREAD_DETACH || dwReason == DLL_PROCESS_DETACH)
2034     {
2035         CExecutionEngine::ThreadDetaching(param.pTlsData);
2036     }
2037     return TRUE;
2038 }
2039
2040 #ifdef DEBUGGING_SUPPORTED
2041 //
2042 // InitializeDebugger initialized the Runtime-side COM+ Debugging Services
2043 //
2044 static void InitializeDebugger(void)
2045 {
2046     CONTRACTL
2047     {
2048         THROWS;
2049         GC_TRIGGERS;
2050         MODE_ANY;
2051     }
2052     CONTRACTL_END;
2053
2054     // Ensure that if we throw, we'll call TerminateDebugger to cleanup.
2055     // This makes our Init more atomic by avoiding partially-init states.
2056     class EnsureCleanup {
2057         BOOL    fNeedCleanup;
2058     public:
2059         EnsureCleanup()
2060         {
2061             fNeedCleanup = TRUE;
2062         }
2063
2064         void SuppressCleanup()
2065         {
2066             fNeedCleanup  = FALSE;
2067         }
2068
2069         ~EnsureCleanup()
2070         {
2071              STATIC_CONTRACT_NOTHROW;
2072              STATIC_CONTRACT_GC_NOTRIGGER;
2073              STATIC_CONTRACT_MODE_ANY;
2074
2075             if (fNeedCleanup) 
2076             { 
2077                 TerminateDebugger();
2078             }
2079         }
2080     } hCleanup;
2081
2082     HRESULT hr = S_OK;
2083
2084     LOG((LF_CORDB, LL_INFO10, "Initializing left-side debugging services.\n"));
2085
2086     FARPROC gi = (FARPROC) &CorDBGetInterface;
2087
2088     // Init the interface the EE provides to the debugger,
2089     // ask the debugger for its interface, and if all goes
2090     // well call Startup on the debugger.
2091     EEDbgInterfaceImpl::Init();
2092     _ASSERTE(g_pEEDbgInterfaceImpl != NULL); // throws on OOM
2093
2094     // This allocates the Debugger object.
2095     typedef HRESULT __cdecl CORDBGETINTERFACE(DebugInterface**);
2096     hr = ((CORDBGETINTERFACE*)gi)(&g_pDebugInterface);
2097     IfFailThrow(hr);
2098
2099     g_pDebugInterface->SetEEInterface(g_pEEDbgInterfaceImpl);
2100
2101     {
2102         hr = g_pDebugInterface->Startup(); // throw on error
2103         _ASSERTE(SUCCEEDED(hr));
2104
2105         // 
2106         // If the debug pack is not installed, Startup will return S_FALSE
2107         // and we should cleanup and proceed without debugging support.
2108         //
2109         if (hr != S_OK)
2110         {
2111             return;
2112         }
2113     }
2114
2115
2116     LOG((LF_CORDB, LL_INFO10, "Left-side debugging services setup.\n"));
2117
2118     hCleanup.SuppressCleanup();
2119
2120     return;
2121 }
2122
2123
2124 //
2125 // TerminateDebugger shuts down the Runtime-side COM+ Debugging Services
2126 // InitializeDebugger will call this if it fails.
2127 // This may be called even if the debugger is partially initialized.
2128 // This can be called multiple times.
2129 //
2130 static void TerminateDebugger(void)
2131 {
2132     CONTRACTL
2133     {
2134         NOTHROW;
2135         GC_NOTRIGGER;
2136         MODE_ANY;
2137     }
2138     CONTRACTL_END;
2139
2140     LOG((LF_CORDB, LL_INFO10, "Shutting down left-side debugger services.\n"));
2141
2142     // If initialized failed really early, then we didn't even get the Debugger object.
2143     if (g_pDebugInterface != NULL)
2144     {
2145         // Notify the out-of-process debugger that shutdown of the in-process debugging support has begun. This is only
2146         // really used in interop debugging scenarios.
2147         g_pDebugInterface->ShutdownBegun();
2148
2149         // This will kill the helper thread, delete the Debugger object, and free all resources.
2150         g_pDebugInterface->StopDebugger();
2151     }
2152
2153     g_CORDebuggerControlFlags = DBCF_NORMAL_OPERATION;
2154
2155 }
2156
2157 #endif // DEBUGGING_SUPPORTED
2158
2159 #ifndef LOCALE_SPARENT
2160 #define LOCALE_SPARENT 0x0000006d
2161 #endif
2162
2163 // ---------------------------------------------------------------------------
2164 // Impl for UtilLoadStringRC Callback: In VM, we let the thread decide culture
2165 // copy culture name into szBuffer and return length
2166 // ---------------------------------------------------------------------------
2167 extern BOOL g_fFatalErrorOccuredOnGCThread;
2168 static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames)
2169 {
2170     CONTRACTL
2171     {
2172         NOTHROW;
2173         GC_NOTRIGGER;
2174         MODE_ANY;
2175         PRECONDITION(CheckPointer(pCultureNames));
2176     } 
2177     CONTRACTL_END;
2178
2179     HRESULT hr = S_OK;
2180
2181     EX_TRY
2182     {
2183         InlineSString<LOCALE_NAME_MAX_LENGTH> sCulture;
2184         InlineSString<LOCALE_NAME_MAX_LENGTH> sParentCulture;
2185
2186 #if 0 // Enable and test if/once the unmanaged runtime is localized
2187         Thread * pThread = GetThread();
2188
2189         // When fatal errors have occured our invariants around GC modes may be broken and attempting to transition to co-op may hang
2190         // 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
2191         // getting localized with a non-default thread-specific culture.
2192         // A canonical stack trace that gets here is a fatal error in the GC that comes through:
2193         // coreclr.dll!GetThreadUICultureNames
2194         // coreclr.dll!CCompRC::LoadLibraryHelper
2195         // coreclr.dll!CCompRC::LoadLibrary
2196         // coreclr.dll!CCompRC::GetLibrary
2197         // coreclr.dll!CCompRC::LoadString
2198         // coreclr.dll!CCompRC::LoadString
2199         // coreclr.dll!SString::LoadResourceAndReturnHR
2200         // coreclr.dll!SString::LoadResourceAndReturnHR
2201         // coreclr.dll!SString::LoadResource
2202         // coreclr.dll!EventReporter::EventReporter
2203         // coreclr.dll!EEPolicy::LogFatalError
2204         // coreclr.dll!EEPolicy::HandleFatalError
2205         if (pThread != NULL && !g_fFatalErrorOccuredOnGCThread) {
2206
2207             // Switch to cooperative mode, since we'll be looking at managed objects
2208             // and we don't want them moving on us.
2209             GCX_COOP();
2210
2211             CULTUREINFOBASEREF pCurrentCulture = (CULTUREINFOBASEREF)Thread::GetCulture(TRUE);
2212
2213             if (pCurrentCulture != NULL)
2214             {
2215                 STRINGREF cultureName = pCurrentCulture->GetName();
2216
2217                 if (cultureName != NULL)
2218                 {
2219                     sCulture.Set(cultureName->GetBuffer(),cultureName->GetStringLength());
2220                 }
2221
2222                 CULTUREINFOBASEREF pParentCulture = pCurrentCulture->GetParent();
2223
2224                 if (pParentCulture != NULL)
2225                 {
2226                     STRINGREF parentCultureName = pParentCulture->GetName();
2227
2228                     if (parentCultureName != NULL)
2229                     {
2230                         sParentCulture.Set(parentCultureName->GetBuffer(),parentCultureName->GetStringLength());
2231                     }
2232
2233                 }
2234             }
2235         }
2236 #endif
2237
2238         // If the lazily-initialized cultureinfo structures aren't initialized yet, we'll
2239         // need to do the lookup the hard way.
2240         if (sCulture.IsEmpty() || sParentCulture.IsEmpty())
2241         {
2242             LocaleIDValue id ;
2243             int tmp; tmp = GetThreadUICultureId(&id);   // TODO: We should use the name instead
2244             _ASSERTE(tmp!=0 && id != UICULTUREID_DONTCARE);
2245             SIZE_T cchParentCultureName=LOCALE_NAME_MAX_LENGTH;
2246             sCulture.Set(id);
2247
2248 #ifndef FEATURE_PAL
2249             if (!::GetLocaleInfoEx((LPCWSTR)sCulture, LOCALE_SPARENT, sParentCulture.OpenUnicodeBuffer(static_cast<COUNT_T>(cchParentCultureName)),static_cast<int>(cchParentCultureName)))
2250             {
2251                 hr = HRESULT_FROM_GetLastError();
2252             }
2253             sParentCulture.CloseBuffer();
2254 #else // !FEATURE_PAL            
2255             sParentCulture = sCulture;
2256 #endif // !FEATURE_PAL            
2257         }
2258         // (LPCWSTR) to restrict the size to null terminated size 
2259         pCultureNames->AppendIfNotThere((LPCWSTR)sCulture);
2260         // Disabling for Dev10 for consistency with managed resource lookup (see AppCompat bug notes in ResourceFallbackManager.cs)
2261         // Also, this is in the wrong order - put after the parent culture chain.
2262         //AddThreadPreferredUILanguages(pCultureNames);
2263         pCultureNames->AppendIfNotThere((LPCWSTR)sParentCulture);
2264         pCultureNames->Append(SString::Empty());
2265     }
2266     EX_CATCH
2267     {
2268         hr=E_OUTOFMEMORY;
2269     }
2270     EX_END_CATCH(SwallowAllExceptions);
2271
2272     return hr;
2273 }
2274
2275 // The exit code for the process is communicated in one of two ways.  If the
2276 // entrypoint returns an 'int' we take that.  Otherwise we take a latched
2277 // process exit code.  This can be modified by the app via System.SetExitCode().
2278 static INT32 LatchedExitCode;
2279     
2280 void SetLatchedExitCode (INT32 code)
2281 {
2282     CONTRACTL
2283     {
2284         NOTHROW;
2285         GC_NOTRIGGER;
2286         MODE_ANY;
2287     }
2288     CONTRACTL_END;
2289
2290     STRESS_LOG1(LF_SYNC, LL_INFO10, "SetLatchedExitCode = %d\n", code);
2291     LatchedExitCode = code;
2292 }
2293
2294 INT32 GetLatchedExitCode (void)
2295 {
2296     LIMITED_METHOD_CONTRACT;
2297     return LatchedExitCode;
2298 }
2299
2300 // ---------------------------------------------------------------------------
2301 // Impl for UtilLoadStringRC Callback: In VM, we let the thread decide culture
2302 // Return an int uniquely describing which language this thread is using for ui.
2303 // ---------------------------------------------------------------------------
2304 static int GetThreadUICultureId(__out LocaleIDValue* pLocale)
2305 {
2306     CONTRACTL{
2307         NOTHROW;
2308         GC_NOTRIGGER;
2309         MODE_ANY;
2310     } CONTRACTL_END;
2311
2312     _ASSERTE(sizeof(LocaleIDValue)/sizeof(WCHAR) >= LOCALE_NAME_MAX_LENGTH);
2313
2314     int Result = 0;
2315
2316     Thread * pThread = GetThread();
2317
2318 #if 0 // Enable and test if/once the unmanaged runtime is localized
2319     // When fatal errors have occured our invariants around GC modes may be broken and attempting to transition to co-op may hang
2320     // 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
2321     // getting localized with a non-default thread-specific culture.
2322     // A canonical stack trace that gets here is a fatal error in the GC that comes through:
2323     // coreclr.dll!GetThreadUICultureNames
2324     // coreclr.dll!CCompRC::LoadLibraryHelper
2325     // coreclr.dll!CCompRC::LoadLibrary
2326     // coreclr.dll!CCompRC::GetLibrary
2327     // coreclr.dll!CCompRC::LoadString
2328     // coreclr.dll!CCompRC::LoadString
2329     // coreclr.dll!SString::LoadResourceAndReturnHR
2330     // coreclr.dll!SString::LoadResourceAndReturnHR
2331     // coreclr.dll!SString::LoadResource
2332     // coreclr.dll!EventReporter::EventReporter
2333     // coreclr.dll!EEPolicy::LogFatalError
2334     // coreclr.dll!EEPolicy::HandleFatalError
2335     if (pThread != NULL && !g_fFatalErrorOccuredOnGCThread)
2336     {
2337
2338         // Switch to cooperative mode, since we'll be looking at managed objects
2339         // and we don't want them moving on us.
2340         GCX_COOP();
2341
2342         CULTUREINFOBASEREF pCurrentCulture = (CULTUREINFOBASEREF)Thread::GetCulture(TRUE);
2343
2344         if (pCurrentCulture != NULL)
2345         {
2346             STRINGREF currentCultureName = pCurrentCulture->GetName();
2347
2348             if (currentCultureName != NULL)
2349             {
2350                 int cchCurrentCultureNameResult = currentCultureName->GetStringLength();
2351                 if (cchCurrentCultureNameResult < LOCALE_NAME_MAX_LENGTH)
2352                 {
2353                     memcpy(*pLocale, currentCultureName->GetBuffer(), cchCurrentCultureNameResult*sizeof(WCHAR));
2354                     (*pLocale)[cchCurrentCultureNameResult]='\0';
2355                     Result=cchCurrentCultureNameResult;
2356                 }
2357             }
2358         }
2359     }
2360 #endif
2361     if (Result == 0)
2362     {
2363 #ifndef FEATURE_PAL
2364         // This thread isn't set up to use a non-default culture. Let's grab the default
2365         // one and return that.
2366
2367         Result = ::GetUserDefaultLocaleName(*pLocale, LOCALE_NAME_MAX_LENGTH);
2368
2369         _ASSERTE(Result != 0);
2370 #else // !FEATURE_PAL
2371         static const WCHAR enUS[] = W("en-US");
2372         memcpy(*pLocale, enUS, sizeof(enUS));
2373         Result = sizeof(enUS);
2374 #endif // !FEATURE_PAL
2375     }
2376     return Result;
2377 }
2378
2379 #ifdef ENABLE_CONTRACTS_IMPL
2380
2381 // Returns TRUE if any contract violation suppressions are in effect.
2382 BOOL AreAnyViolationBitsOn()
2383 {
2384     CONTRACTL
2385     {
2386         NOTHROW;
2387         GC_NOTRIGGER;
2388         MODE_ANY;
2389     }
2390     CONTRACTL_END;
2391     UINT_PTR violationMask = GetClrDebugState()->ViolationMask();
2392     violationMask &= ~((UINT_PTR)CanFreeMe);  //CanFreeMe is a borrowed bit and has nothing to do with violations
2393     if (violationMask & ((UINT_PTR)BadDebugState))
2394     {
2395         return FALSE;
2396     }
2397
2398     return violationMask != 0;
2399 }
2400
2401
2402 // This function is intentionally invoked inside a big CONTRACT_VIOLATION that turns on every violation
2403 // bit on the map. The dynamic contract at the beginning *should* turn off those violation bits. 
2404 // The body of this function tests to see that it did exactly that. This is to prevent the VSWhidbey B#564831 fiasco
2405 // from ever recurring.
2406 void ContractRegressionCheckInner()
2407 {
2408     // DO NOT TURN THIS CONTRACT INTO A STATIC CONTRACT!!! The very purpose of this function
2409     // is to ensure that dynamic contracts disable outstanding contract violation bits.
2410     // This code only runs once at process startup so it's not going pooch the checked build perf.
2411     CONTRACTL
2412     {
2413         NOTHROW;
2414         GC_NOTRIGGER;
2415         FORBID_FAULT;
2416         LOADS_TYPE(CLASS_LOAD_BEGIN);
2417         CANNOT_TAKE_LOCK;
2418     }
2419     CONTRACTL_END
2420
2421     if (AreAnyViolationBitsOn())
2422     {
2423         // If we got here, the contract above FAILED to turn off one or more violation bits. This is a 
2424         // huge diagnostics hole and must be fixed immediately.
2425         _ASSERTE(!("WARNING: mscorwks has detected an internal error that may indicate contracts are"
2426                    " being silently disabled across the runtime. Do not ignore this assert!"));
2427     }
2428 }
2429
2430 // This function executes once per process to ensure our CONTRACT_VIOLATION() mechanism 
2431 // is properly scope-limited by nested contracts.
2432 void ContractRegressionCheck()
2433 {
2434     CONTRACTL
2435     {
2436         NOTHROW;
2437         GC_NOTRIGGER;
2438         MODE_ANY;
2439     }
2440     CONTRACTL_END;
2441  
2442     {
2443         // DO NOT "FIX" THIS CONTRACT_VIOLATION!!!
2444         // The existence of this CONTRACT_VIOLATION is not a bug. This is debug-only code specifically written
2445         // to test the CONTRACT_VIOLATION mechanism itself. This is needed to prevent a regression of 
2446         // B#564831 (which left a huge swath of contracts silently disabled for over six months)
2447         PERMANENT_CONTRACT_VIOLATION(ThrowsViolation
2448                                    | GCViolation
2449                                    | FaultViolation
2450                                    | LoadsTypeViolation
2451                                    | TakesLockViolation
2452                                    , ReasonContractInfrastructure
2453                                     );
2454         {
2455             FAULT_NOT_FATAL();
2456             ContractRegressionCheckInner();
2457         }
2458     }
2459
2460     if (AreAnyViolationBitsOn())
2461     {
2462         // If we got here, the CONTRACT_VIOLATION() holder left one or more violation bits turned ON
2463         // after we left its scope. This is a huge diagnostic hole and must be fixed immediately.
2464         _ASSERTE(!("WARNING: mscorwks has detected an internal error that may indicate contracts are"
2465                    " being silently disabled across the runtime. Do not ignore this assert!"));
2466     }
2467
2468 }
2469
2470 #endif // ENABLE_CONTRACTS_IMPL
2471
2472 #endif // CROSSGEN_COMPILE