Bug 1833854 - Part 2: Common up GCSchedulingTunables invariant checks r=sfink
[gecko.git] / xpcom / build / XPCOMInit.cpp
blobcd6c7f705289233167b254037db2e7bb5d3b796f
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ThreadEventTarget.h"
8 #include "XPCOMModule.h"
10 #include "base/basictypes.h"
12 #include "mozilla/AbstractThread.h"
13 #include "mozilla/AppShutdown.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Atomics.h"
16 #include "mozilla/DebugOnly.h"
17 #include "mozilla/Poison.h"
18 #include "mozilla/SharedThreadPool.h"
19 #include "mozilla/TaskController.h"
20 #include "mozilla/Unused.h"
21 #include "mozilla/XPCOM.h"
22 #include "mozJSModuleLoader.h"
23 #include "nsXULAppAPI.h"
25 #ifndef ANDROID
26 # include "nsTerminator.h"
27 #endif
29 #include "nsXPCOMPrivate.h"
30 #include "nsXPCOMCIDInternal.h"
32 #include "mozilla/dom/JSExecutionManager.h"
33 #include "mozilla/layers/ImageBridgeChild.h"
34 #include "mozilla/layers/CompositorBridgeParent.h"
36 #include "prlink.h"
38 #include "nsCycleCollector.h"
39 #include "nsObserverService.h"
41 #include "nsDebugImpl.h"
42 #include "nsSystemInfo.h"
44 #include "nsComponentManager.h"
45 #include "nsCategoryManagerUtils.h"
46 #include "nsIServiceManager.h"
48 #include "nsThreadManager.h"
49 #include "nsThreadPool.h"
51 #include "nsTimerImpl.h"
52 #include "TimerThread.h"
54 #include "nsThread.h"
55 #include "nsVersionComparatorImpl.h"
57 #include "nsIFile.h"
58 #include "nsLocalFile.h"
59 #include "nsDirectoryService.h"
60 #include "nsDirectoryServiceDefs.h"
61 #include "nsCategoryManager.h"
62 #include "nsMultiplexInputStream.h"
64 #include "nsAtomTable.h"
65 #include "nsISupportsImpl.h"
67 #include "nsSystemInfo.h"
68 #include "nsMemoryReporterManager.h"
69 #include "nsMessageLoop.h"
70 #include "nss.h"
71 #include "nsNSSComponent.h"
73 #include <locale.h>
74 #include "mozilla/Services.h"
75 #include "mozilla/Omnijar.h"
76 #include "mozilla/ScriptPreloader.h"
77 #include "mozilla/Telemetry.h"
78 #include "mozilla/BackgroundHangMonitor.h"
80 #include "mozilla/PoisonIOInterposer.h"
81 #include "mozilla/LateWriteChecks.h"
83 #include "mozilla/scache/StartupCache.h"
85 #include "base/at_exit.h"
86 #include "base/command_line.h"
87 #include "base/message_loop.h"
89 #include "mozilla/ipc/BrowserProcessSubThread.h"
90 #include "mozilla/AvailableMemoryTracker.h"
91 #include "mozilla/ClearOnShutdown.h"
92 #include "mozilla/CountingAllocatorBase.h"
93 #include "mozilla/UniquePtr.h"
94 #include "mozilla/ServoStyleConsts.h"
96 #include "mozilla/ipc/GeckoChildProcessHost.h"
98 #include "ogg/ogg.h"
100 #include "GeckoProfiler.h"
101 #include "ProfilerControl.h"
103 #include "jsapi.h"
104 #include "js/Initialization.h"
105 #include "mozilla/StaticPrefs_javascript.h"
106 #include "XPCSelfHostedShmem.h"
108 #include "gfxPlatform.h"
110 using base::AtExitManager;
111 using mozilla::ipc::BrowserProcessSubThread;
113 // From toolkit/library/rust/lib.rs
114 extern "C" void GkRust_Init();
115 extern "C" void GkRust_Shutdown();
117 namespace {
119 static AtExitManager* sExitManager;
120 static MessageLoop* sMessageLoop;
121 static bool sCommandLineWasInitialized;
122 static BrowserProcessSubThread* sIOThread;
123 static mozilla::BackgroundHangMonitor* sMainHangMonitor;
125 } /* anonymous namespace */
127 // Registry Factory creation function defined in nsRegistry.cpp
128 // We hook into this function locally to create and register the registry
129 // Since noone outside xpcom needs to know about this and nsRegistry.cpp
130 // does not have a local include file, we are putting this definition
131 // here rather than in nsIRegistry.h
132 extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
133 extern nsresult NS_CategoryManagerGetFactory(nsIFactory**);
135 #ifdef XP_WIN
136 extern nsresult CreateAnonTempFileRemover();
137 #endif
139 nsresult nsThreadManagerGetSingleton(const nsIID& aIID, void** aInstancePtr) {
140 NS_ASSERTION(aInstancePtr, "null outptr");
141 return nsThreadManager::get().QueryInterface(aIID, aInstancePtr);
144 nsresult nsLocalFileConstructor(const nsIID& aIID, void** aInstancePtr) {
145 return nsLocalFile::nsLocalFileConstructor(aIID, aInstancePtr);
148 nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = nullptr;
149 bool gXPCOMShuttingDown = false;
150 bool gXPCOMMainThreadEventsAreDoomed = false;
151 char16_t* gGREBinPath = nullptr;
153 // gDebug will be freed during shutdown.
154 static nsIDebug2* gDebug = nullptr;
156 EXPORT_XPCOM_API(nsresult)
157 NS_GetDebug(nsIDebug2** aResult) {
158 return nsDebugImpl::Create(NS_GET_IID(nsIDebug2), (void**)aResult);
161 class ICUReporter final : public nsIMemoryReporter,
162 public mozilla::CountingAllocatorBase<ICUReporter> {
163 public:
164 NS_DECL_ISUPPORTS
166 static void* Alloc(const void*, size_t aSize) {
167 return CountingMalloc(aSize);
170 static void* Realloc(const void*, void* aPtr, size_t aSize) {
171 return CountingRealloc(aPtr, aSize);
174 static void Free(const void*, void* aPtr) { return CountingFree(aPtr); }
176 private:
177 NS_IMETHOD
178 CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
179 bool aAnonymize) override {
180 MOZ_COLLECT_REPORT(
181 "explicit/icu", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
182 "Memory used by ICU, a Unicode and globalization support library.");
184 return NS_OK;
187 ~ICUReporter() = default;
190 NS_IMPL_ISUPPORTS(ICUReporter, nsIMemoryReporter)
192 class OggReporter final : public nsIMemoryReporter,
193 public mozilla::CountingAllocatorBase<OggReporter> {
194 public:
195 NS_DECL_ISUPPORTS
197 private:
198 NS_IMETHOD
199 CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
200 bool aAnonymize) override {
201 MOZ_COLLECT_REPORT(
202 "explicit/media/libogg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
203 "Memory allocated through libogg for Ogg, Theora, and related media "
204 "files.");
206 return NS_OK;
209 ~OggReporter() = default;
212 NS_IMPL_ISUPPORTS(OggReporter, nsIMemoryReporter)
214 static bool sInitializedJS = false;
216 static void InitializeJS() {
217 #if defined(ENABLE_WASM_SIMD) && \
218 (defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86))
219 // Update static engine preferences, such as AVX, before
220 // `JS_InitWithFailureDiagnostic` is called.
221 JS::SetAVXEnabled(mozilla::StaticPrefs::javascript_options_wasm_simd_avx());
222 #endif
224 const char* jsInitFailureReason = JS_InitWithFailureDiagnostic();
225 if (jsInitFailureReason) {
226 MOZ_CRASH_UNSAFE(jsInitFailureReason);
230 // Note that on OSX, aBinDirectory will point to .app/Contents/Resources/browser
231 EXPORT_XPCOM_API(nsresult)
232 NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
233 nsIDirectoryServiceProvider* aAppFileLocationProvider,
234 bool aInitJSContext) {
235 static bool sInitialized = false;
236 if (sInitialized) {
237 return NS_ERROR_FAILURE;
240 sInitialized = true;
242 NS_LogInit();
244 NS_InitAtomTable();
246 // We don't have the arguments by hand here. If logging has already been
247 // initialized by a previous call to LogModule::Init with the arguments
248 // passed, passing (0, nullptr) is alright here.
249 mozilla::LogModule::Init(0, nullptr);
251 GkRust_Init();
253 nsresult rv = NS_OK;
255 // We are not shutting down
256 gXPCOMShuttingDown = false;
258 #ifdef XP_UNIX
259 // Discover the current value of the umask, and save it where
260 // nsSystemInfo::Init can retrieve it when necessary. There is no way
261 // to read the umask without changing it, and the setting is process-
262 // global, so this must be done while we are still single-threaded; the
263 // nsSystemInfo object is typically created much later, when some piece
264 // of chrome JS wants it. The system call is specified as unable to fail.
265 nsSystemInfo::gUserUmask = ::umask(0777);
266 ::umask(nsSystemInfo::gUserUmask);
267 #endif
269 // Set up chromium libs
270 NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
272 if (!AtExitManager::AlreadyRegistered()) {
273 sExitManager = new AtExitManager();
276 MessageLoop* messageLoop = MessageLoop::current();
277 if (!messageLoop) {
278 sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT);
279 sMessageLoop->set_thread_name("Gecko");
280 // Set experimental values for main thread hangs:
281 // 128ms for transient hangs and 8192ms for permanent hangs
282 sMessageLoop->set_hang_timeouts(128, 8192);
283 } else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) {
284 messageLoop->set_thread_name("Gecko_Child");
285 messageLoop->set_hang_timeouts(128, 8192);
288 if (XRE_IsParentProcess() &&
289 !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) {
290 mozilla::UniquePtr<BrowserProcessSubThread> ioThread =
291 mozilla::MakeUnique<BrowserProcessSubThread>(
292 BrowserProcessSubThread::IO);
294 base::Thread::Options options;
295 options.message_loop_type = MessageLoop::TYPE_IO;
296 if (NS_WARN_IF(!ioThread->StartWithOptions(options))) {
297 return NS_ERROR_FAILURE;
300 sIOThread = ioThread.release();
303 // Establish the main thread here.
304 rv = nsThreadManager::get().Init();
305 if (NS_WARN_IF(NS_FAILED(rv))) {
306 return rv;
308 AUTO_PROFILER_INIT2;
310 // Set up the timer globals/timer thread
311 rv = nsTimerImpl::Startup();
312 if (NS_WARN_IF(NS_FAILED(rv))) {
313 return rv;
316 #ifndef ANDROID
317 // If the locale hasn't already been setup by our embedder,
318 // get us out of the "C" locale and into the system
319 if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) {
320 setlocale(LC_ALL, "");
322 #endif
324 nsDirectoryService::RealInit();
326 bool value;
328 if (aBinDirectory) {
329 rv = aBinDirectory->IsDirectory(&value);
331 if (NS_SUCCEEDED(rv) && value) {
332 nsDirectoryService::gService->SetCurrentProcessDirectory(aBinDirectory);
336 if (aAppFileLocationProvider) {
337 rv = nsDirectoryService::gService->RegisterProvider(
338 aAppFileLocationProvider);
339 if (NS_FAILED(rv)) {
340 return rv;
344 nsCOMPtr<nsIFile> xpcomLib;
345 nsDirectoryService::gService->Get(NS_GRE_BIN_DIR, NS_GET_IID(nsIFile),
346 getter_AddRefs(xpcomLib));
347 MOZ_ASSERT(xpcomLib);
349 // set gGREBinPath
350 nsAutoString path;
351 xpcomLib->GetPath(path);
352 gGREBinPath = ToNewUnicode(path);
354 xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
355 nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
357 if (!mozilla::Omnijar::IsInitialized()) {
358 mozilla::Omnijar::Init();
361 if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
362 #ifdef OS_WIN
363 CommandLine::Init(0, nullptr);
364 #else
365 nsCOMPtr<nsIFile> binaryFile;
366 nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
367 NS_GET_IID(nsIFile),
368 getter_AddRefs(binaryFile));
369 if (NS_WARN_IF(!binaryFile)) {
370 return NS_ERROR_FAILURE;
373 rv = binaryFile->AppendNative("nonexistent-executable"_ns);
374 if (NS_WARN_IF(NS_FAILED(rv))) {
375 return rv;
378 nsCString binaryPath;
379 rv = binaryFile->GetNativePath(binaryPath);
380 if (NS_WARN_IF(NS_FAILED(rv))) {
381 return rv;
384 static char const* const argv = {strdup(binaryPath.get())};
385 CommandLine::Init(1, &argv);
386 #endif
389 NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr,
390 "CompMgr not null at init");
392 // Create the Component/Service Manager
393 nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
394 NS_ADDREF(nsComponentManagerImpl::gComponentManager);
396 // Global cycle collector initialization.
397 if (!nsCycleCollector_init()) {
398 return NS_ERROR_UNEXPECTED;
401 // And start it up for this thread too.
402 nsCycleCollector_startup();
404 // Register ICU memory functions. This really shouldn't be necessary: the
405 // JS engine should do this on its own inside JS_Init, and memory-reporting
406 // code should call a JSAPI function to observe ICU memory usage. But we
407 // can't define the alloc/free functions in the JS engine, because it can't
408 // depend on the XPCOM-based memory reporting goop. So for now, we have
409 // this oddness.
410 mozilla::SetICUMemoryFunctions();
412 // Do the same for libogg.
413 ogg_set_mem_functions(
414 OggReporter::CountingMalloc, OggReporter::CountingCalloc,
415 OggReporter::CountingRealloc, OggReporter::CountingFree);
417 // Initialize the JS engine.
418 InitializeJS();
419 sInitializedJS = true;
421 rv = nsComponentManagerImpl::gComponentManager->Init();
422 if (NS_FAILED(rv)) {
423 NS_RELEASE(nsComponentManagerImpl::gComponentManager);
424 return rv;
427 if (aResult) {
428 NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
431 // After autoreg, but before we actually instantiate any components,
432 // add any services listed in the "xpcom-directory-providers" category
433 // to the directory service.
434 nsDirectoryService::gService->RegisterCategoryProviders();
436 // Init mozilla::SharedThreadPool (which needs the service manager).
437 mozilla::SharedThreadPool::InitStatics();
439 mozilla::scache::StartupCache::GetSingleton();
440 mozilla::AvailableMemoryTracker::Init();
442 // Notify observers of xpcom autoregistration start
443 NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nullptr,
444 NS_XPCOM_STARTUP_OBSERVER_ID);
445 #ifdef XP_WIN
446 CreateAnonTempFileRemover();
447 #endif
449 // The memory reporter manager is up and running -- register our reporters.
450 RegisterStrongMemoryReporter(new ICUReporter());
451 RegisterStrongMemoryReporter(new OggReporter());
452 xpc::SelfHostedShmem::GetSingleton().InitMemoryReporter();
454 mozilla::Telemetry::Init();
456 mozilla::BackgroundHangMonitor::Startup();
458 const MessageLoop* const loop = MessageLoop::current();
459 sMainHangMonitor = new mozilla::BackgroundHangMonitor(
460 loop->thread_name().c_str(), loop->transient_hang_timeout(),
461 loop->permanent_hang_timeout());
463 mozilla::dom::JSExecutionManager::Initialize();
465 if (aInitJSContext) {
466 xpc::InitializeJSContext();
469 return NS_OK;
472 EXPORT_XPCOM_API(nsresult)
473 NS_InitMinimalXPCOM() {
474 NS_SetMainThread();
475 mozilla::TimeStamp::Startup();
476 NS_LogInit();
477 NS_InitAtomTable();
479 // We don't have the arguments by hand here. If logging has already been
480 // initialized by a previous call to LogModule::Init with the arguments
481 // passed, passing (0, nullptr) is alright here.
482 mozilla::LogModule::Init(0, nullptr);
484 GkRust_Init();
486 nsresult rv = nsThreadManager::get().Init();
487 if (NS_WARN_IF(NS_FAILED(rv))) {
488 return rv;
491 // Set up the timer globals/timer thread.
492 rv = nsTimerImpl::Startup();
493 if (NS_WARN_IF(NS_FAILED(rv))) {
494 return rv;
497 // Create the Component/Service Manager
498 nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
499 NS_ADDREF(nsComponentManagerImpl::gComponentManager);
501 rv = nsComponentManagerImpl::gComponentManager->Init();
502 if (NS_FAILED(rv)) {
503 NS_RELEASE(nsComponentManagerImpl::gComponentManager);
504 return rv;
507 // Global cycle collector initialization.
508 if (!nsCycleCollector_init()) {
509 return NS_ERROR_UNEXPECTED;
512 mozilla::SharedThreadPool::InitStatics();
513 mozilla::Telemetry::Init();
514 mozilla::BackgroundHangMonitor::Startup();
516 return NS_OK;
520 // NS_ShutdownXPCOM()
522 // The shutdown sequence for xpcom would be
524 // - Notify "xpcom-shutdown" for modules to release primary (root) references
525 // - Shutdown XPCOM timers
526 // - Notify "xpcom-shutdown-threads" for thread joins
527 // - Shutdown the event queues
528 // - Release the Global Service Manager
529 // - Release all service instances held by the global service manager
530 // - Release the Global Service Manager itself
531 // - Release the Component Manager
532 // - Release all factories cached by the Component Manager
533 // - Notify module loaders to shut down
534 // - Unload Libraries
535 // - Release Contractid Cache held by Component Manager
536 // - Release dll abstraction held by Component Manager
537 // - Release the Registry held by Component Manager
538 // - Finally, release the component manager itself
540 EXPORT_XPCOM_API(nsresult)
541 NS_ShutdownXPCOM(nsIServiceManager* aServMgr) {
542 return mozilla::ShutdownXPCOM(aServMgr);
545 namespace mozilla {
547 void SetICUMemoryFunctions() {
548 static bool sICUReporterInitialized = false;
549 if (!sICUReporterInitialized) {
550 if (!JS_SetICUMemoryFunctions(ICUReporter::Alloc, ICUReporter::Realloc,
551 ICUReporter::Free)) {
552 MOZ_CRASH("JS_SetICUMemoryFunctions failed.");
554 sICUReporterInitialized = true;
558 nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) {
559 // Make sure the hang monitor is enabled for shutdown.
560 BackgroundHangMonitor().NotifyActivity();
562 if (!NS_IsMainThread()) {
563 MOZ_CRASH("Shutdown on wrong thread");
566 // Notify observers of xpcom shutting down
568 // Block it so that the COMPtr will get deleted before we hit
569 // servicemanager shutdown
571 nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
572 if (NS_WARN_IF(!thread)) {
573 return NS_ERROR_UNEXPECTED;
576 mozilla::AppShutdown::AdvanceShutdownPhase(
577 mozilla::ShutdownPhase::XPCOMWillShutdown);
579 // We want the service manager to be the subject of notifications
580 nsCOMPtr<nsIServiceManager> mgr;
581 Unused << NS_GetServiceManager(getter_AddRefs(mgr));
582 MOZ_DIAGNOSTIC_ASSERT(mgr != nullptr, "Service manager not present!");
583 mozilla::AppShutdown::AdvanceShutdownPhase(
584 mozilla::ShutdownPhase::XPCOMShutdown, nullptr, do_QueryInterface(mgr));
586 // This must happen after the shutdown of media and widgets, which
587 // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
588 gfxPlatform::ShutdownLayersIPC();
590 mozilla::AppShutdown::AdvanceShutdownPhase(
591 mozilla::ShutdownPhase::XPCOMShutdownThreads);
592 #ifdef DEBUG
593 // Prime an assertion at ThreadEventTarget::Dispatch to avoid late
594 // dispatches to non main-thread threads.
595 ThreadEventTarget::XPCOMShutdownThreadsNotificationFinished();
596 #endif
598 // Shutdown the timer thread and all timers that might still be alive
599 nsTimerImpl::Shutdown();
601 // Have an extra round of processing after the timers went away.
602 NS_ProcessPendingEvents(thread);
604 // Shutdown all remaining threads. This method does not return until
605 // all threads created using the thread manager (with the exception of
606 // the main thread) have exited.
607 nsThreadManager::get().ShutdownNonMainThreads();
609 RefPtr<nsObserverService> observerService;
610 CallGetService("@mozilla.org/observer-service;1",
611 (nsObserverService**)getter_AddRefs(observerService));
612 if (observerService) {
613 observerService->Shutdown();
616 // XPCOMShutdownFinal is the default phase for ClearOnShutdown.
617 // This AdvanceShutdownPhase will thus free most ClearOnShutdown()'ed
618 // smart pointers. Some destructors may fire extra main thread runnables
619 // that will be processed inside AdvanceShutdownPhase.
620 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::XPCOMShutdownFinal);
622 // Shutdown the main thread, processing our very last round of events, and
623 // then mark that we've finished main thread event processing.
624 nsThreadManager::get().ShutdownMainThread();
625 gXPCOMMainThreadEventsAreDoomed = true;
627 BackgroundHangMonitor().NotifyActivity();
629 mozilla::dom::JSExecutionManager::Shutdown();
632 // XPCOM is officially in shutdown mode NOW
633 // Set this only after the observers have been notified as this
634 // will cause servicemanager to become inaccessible.
635 mozilla::services::Shutdown();
637 // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
638 // here again:
639 NS_IF_RELEASE(aServMgr);
641 // Shutdown global servicemanager
642 if (nsComponentManagerImpl::gComponentManager) {
643 nsComponentManagerImpl::gComponentManager->FreeServices();
646 // Remove the remaining main thread representations
647 nsThreadManager::get().ReleaseMainThread();
648 AbstractThread::ShutdownMainThread();
650 // Release the directory service
651 nsDirectoryService::gService = nullptr;
653 free(gGREBinPath);
654 gGREBinPath = nullptr;
656 // FIXME: This can cause harmless writes from sqlite committing
657 // log files. We have to ignore them before we can move
658 // the mozilla::PoisonWrite call before this point. See bug
659 // 834945 for the details.
660 mozJSModuleLoader::UnloadLoaders();
662 // Clear the profiler's JS context before cycle collection. The profiler will
663 // notify the JS engine that it can let go of any data it's holding on to for
664 // profiling purposes.
665 PROFILER_CLEAR_JS_CONTEXT();
667 bool shutdownCollect;
668 #ifdef NS_FREE_PERMANENT_DATA
669 shutdownCollect = true;
670 #else
671 shutdownCollect = !!PR_GetEnv("MOZ_CC_RUN_DURING_SHUTDOWN");
672 #endif
673 nsCycleCollector_shutdown(shutdownCollect);
675 // There can be code trying to refer to global objects during the final cc
676 // shutdown. This is the phase for such global objects to correctly release.
677 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::CCPostLastCycleCollection);
679 mozilla::scache::StartupCache::DeleteSingleton();
680 mozilla::ScriptPreloader::DeleteSingleton();
682 PROFILER_MARKER_UNTYPED("Shutdown xpcom", OTHER);
684 // Shutdown xpcom. This will release all loaders and cause others holding
685 // a refcount to the component manager to release it.
686 if (nsComponentManagerImpl::gComponentManager) {
687 DebugOnly<nsresult> rv =
688 (nsComponentManagerImpl::gComponentManager)->Shutdown();
689 NS_ASSERTION(NS_SUCCEEDED(rv.value), "Component Manager shutdown failed.");
690 } else {
691 NS_WARNING("Component Manager was never created ...");
694 if (sInitializedJS) {
695 // Shut down the JS engine.
696 JS_ShutDown();
697 sInitializedJS = false;
700 mozilla::ScriptPreloader::DeleteCacheDataSingleton();
702 // Release shared memory which might be borrowed by the JS engine.
703 xpc::SelfHostedShmem::Shutdown();
705 // After all threads have been joined and the component manager has been shut
706 // down, any remaining objects that could be holding NSS resources (should)
707 // have been released, so we can safely shut down NSS.
708 if (NSS_IsInitialized()) {
709 nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
710 if (NSS_Shutdown() != SECSuccess) {
711 // If you're seeing this crash and/or warning, some NSS resources are
712 // still in use (see bugs 1417680 and 1230312). Set the environment
713 // variable 'MOZ_IGNORE_NSS_SHUTDOWN_LEAKS' to some value to ignore this.
714 // Also, if leak checking is enabled, report this as a fake leak instead
715 // of crashing.
716 #if defined(DEBUG) && !defined(ANDROID)
717 if (!getenv("MOZ_IGNORE_NSS_SHUTDOWN_LEAKS") &&
718 !getenv("XPCOM_MEM_BLOAT_LOG") && !getenv("XPCOM_MEM_LEAK_LOG") &&
719 !getenv("XPCOM_MEM_REFCNT_LOG") && !getenv("XPCOM_MEM_COMPTR_LOG")) {
720 MOZ_CRASH("NSS_Shutdown failed");
721 } else {
722 # ifdef NS_BUILD_REFCNT_LOGGING
723 // Create a fake leak.
724 NS_LogCtor((void*)0x100, "NSSShutdownFailed", 100);
725 # endif // NS_BUILD_REFCNT_LOGGING
726 NS_WARNING("NSS_Shutdown failed");
728 #else
729 NS_WARNING("NSS_Shutdown failed");
730 #endif // defined(DEBUG) && !defined(ANDROID)
734 // Finally, release the component manager last because it unloads the
735 // libraries:
736 if (nsComponentManagerImpl::gComponentManager) {
737 nsrefcnt cnt;
738 NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
739 NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown.");
741 nsComponentManagerImpl::gComponentManager = nullptr;
742 nsCategoryManager::Destroy();
744 GkRust_Shutdown();
746 #ifdef NS_FREE_PERMANENT_DATA
747 // By the time we're shutting down, there may still be async parse tasks going
748 // on in the Servo thread-pool. This is fairly uncommon, though not
749 // impossible. CSS parsing heavily uses the atom table, so obviously it's not
750 // fine to get rid of it.
752 // In leak-checking / ASAN / etc. builds, shut down the servo thread-pool,
753 // which will wait for all the work to be done. For other builds, we don't
754 // really want to wait on shutdown for possibly slow tasks. So just leak the
755 // atom table in those.
756 Servo_ShutdownThreadPool();
757 NS_ShutdownAtomTable();
758 #endif
760 NS_IF_RELEASE(gDebug);
762 delete sIOThread;
763 sIOThread = nullptr;
765 delete sMessageLoop;
766 sMessageLoop = nullptr;
768 mozilla::TaskController::Shutdown();
770 if (sCommandLineWasInitialized) {
771 CommandLine::Terminate();
772 sCommandLineWasInitialized = false;
775 delete sExitManager;
776 sExitManager = nullptr;
778 Omnijar::CleanUp();
780 BackgroundHangMonitor::Shutdown();
782 delete sMainHangMonitor;
783 sMainHangMonitor = nullptr;
785 NS_LogTerm();
787 return NS_OK;
790 } // namespace mozilla