Bug 1883861 - Part 1: Move visitMemoryBarrier into the common CodeGenerator file...
[gecko.git] / xpcom / build / XPCOMInit.cpp
blob4d6572a501d251446fe11669c1c57ebdce992afd
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"
66 #include "nsLanguageAtomService.h"
68 #include "nsSystemInfo.h"
69 #include "nsMemoryReporterManager.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 #ifdef MOZ_PHC
94 # include "mozilla/PHCManager.h"
95 #endif
96 #include "mozilla/UniquePtr.h"
97 #include "mozilla/ServoStyleConsts.h"
99 #include "mozilla/ipc/GeckoChildProcessHost.h"
101 #include "ogg/ogg.h"
103 #include "GeckoProfiler.h"
104 #include "ProfilerControl.h"
106 #include "jsapi.h"
107 #include "js/Initialization.h"
108 #include "js/Prefs.h"
109 #include "mozilla/StaticPrefs_javascript.h"
110 #include "XPCSelfHostedShmem.h"
112 #include "gfxPlatform.h"
114 using base::AtExitManager;
115 using mozilla::ipc::BrowserProcessSubThread;
117 // From toolkit/library/rust/lib.rs
118 extern "C" void GkRust_Init();
119 extern "C" void GkRust_Shutdown();
121 namespace {
123 static AtExitManager* sExitManager;
124 static MessageLoop* sMessageLoop;
125 static bool sCommandLineWasInitialized;
126 static BrowserProcessSubThread* sIOThread;
127 static mozilla::BackgroundHangMonitor* sMainHangMonitor;
129 } /* anonymous namespace */
131 // Registry Factory creation function defined in nsRegistry.cpp
132 // We hook into this function locally to create and register the registry
133 // Since noone outside xpcom needs to know about this and nsRegistry.cpp
134 // does not have a local include file, we are putting this definition
135 // here rather than in nsIRegistry.h
136 extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
137 extern nsresult NS_CategoryManagerGetFactory(nsIFactory**);
139 #ifdef XP_WIN
140 extern nsresult CreateAnonTempFileRemover();
141 #endif
143 nsresult nsThreadManagerGetSingleton(const nsIID& aIID, void** aInstancePtr) {
144 NS_ASSERTION(aInstancePtr, "null outptr");
145 return nsThreadManager::get().QueryInterface(aIID, aInstancePtr);
148 nsresult nsLocalFileConstructor(const nsIID& aIID, void** aInstancePtr) {
149 return nsLocalFile::nsLocalFileConstructor(aIID, aInstancePtr);
152 nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = nullptr;
153 bool gXPCOMShuttingDown = false;
154 bool gXPCOMMainThreadEventsAreDoomed = false;
155 char16_t* gGREBinPath = nullptr;
157 // gDebug will be freed during shutdown.
158 static nsIDebug2* gDebug = nullptr;
160 EXPORT_XPCOM_API(nsresult)
161 NS_GetDebug(nsIDebug2** aResult) {
162 return nsDebugImpl::Create(NS_GET_IID(nsIDebug2), (void**)aResult);
165 class ICUReporter final : public nsIMemoryReporter,
166 public mozilla::CountingAllocatorBase<ICUReporter> {
167 public:
168 NS_DECL_ISUPPORTS
170 static void* Alloc(const void*, size_t aSize) {
171 void* result = CountingMalloc(aSize);
172 if (result == nullptr) {
173 MOZ_CRASH("Ran out of memory while allocating for ICU");
175 return result;
178 static void* Realloc(const void*, void* aPtr, size_t aSize) {
179 void* result = CountingRealloc(aPtr, aSize);
180 if (result == nullptr) {
181 MOZ_CRASH("Ran out of memory while reallocating for ICU");
183 return result;
186 static void Free(const void*, void* aPtr) { return CountingFree(aPtr); }
188 private:
189 NS_IMETHOD
190 CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
191 bool aAnonymize) override {
192 MOZ_COLLECT_REPORT(
193 "explicit/icu", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
194 "Memory used by ICU, a Unicode and globalization support library.");
196 return NS_OK;
199 ~ICUReporter() = default;
202 NS_IMPL_ISUPPORTS(ICUReporter, nsIMemoryReporter)
204 class OggReporter final : public nsIMemoryReporter,
205 public mozilla::CountingAllocatorBase<OggReporter> {
206 public:
207 NS_DECL_ISUPPORTS
209 private:
210 NS_IMETHOD
211 CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
212 bool aAnonymize) override {
213 MOZ_COLLECT_REPORT(
214 "explicit/media/libogg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
215 "Memory allocated through libogg for Ogg, Theora, and related media "
216 "files.");
218 return NS_OK;
221 ~OggReporter() = default;
224 NS_IMPL_ISUPPORTS(OggReporter, nsIMemoryReporter)
226 static bool sInitializedJS = false;
228 static void InitializeJS() {
229 #if defined(ENABLE_WASM_SIMD) && \
230 (defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86))
231 // Update static engine preferences, such as AVX, before
232 // `JS_InitWithFailureDiagnostic` is called.
233 JS::SetAVXEnabled(mozilla::StaticPrefs::javascript_options_wasm_simd_avx());
234 #endif
236 // Set all JS::Prefs.
237 SET_JS_PREFS_FROM_BROWSER_PREFS;
239 const char* jsInitFailureReason = JS_InitWithFailureDiagnostic();
240 if (jsInitFailureReason) {
241 MOZ_CRASH_UNSAFE(jsInitFailureReason);
245 // Note that on OSX, aBinDirectory will point to .app/Contents/Resources/browser
246 EXPORT_XPCOM_API(nsresult)
247 NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
248 nsIDirectoryServiceProvider* aAppFileLocationProvider,
249 bool aInitJSContext) {
250 static bool sInitialized = false;
251 if (sInitialized) {
252 return NS_ERROR_FAILURE;
255 sInitialized = true;
257 NS_LogInit();
259 NS_InitAtomTable();
261 // We don't have the arguments by hand here. If logging has already been
262 // initialized by a previous call to LogModule::Init with the arguments
263 // passed, passing (0, nullptr) is alright here.
264 mozilla::LogModule::Init(0, nullptr);
266 GkRust_Init();
268 nsresult rv = NS_OK;
270 // We are not shutting down
271 gXPCOMShuttingDown = false;
273 #ifdef XP_UNIX
274 // Discover the current value of the umask, and save it where
275 // nsSystemInfo::Init can retrieve it when necessary. There is no way
276 // to read the umask without changing it, and the setting is process-
277 // global, so this must be done while we are still single-threaded; the
278 // nsSystemInfo object is typically created much later, when some piece
279 // of chrome JS wants it. The system call is specified as unable to fail.
280 nsSystemInfo::gUserUmask = ::umask(0777);
281 ::umask(nsSystemInfo::gUserUmask);
282 #endif
284 // Set up chromium libs
285 NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
287 if (!AtExitManager::AlreadyRegistered()) {
288 sExitManager = new AtExitManager();
291 MessageLoop* messageLoop = MessageLoop::current();
292 if (!messageLoop) {
293 sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT);
294 sMessageLoop->set_thread_name("Gecko");
295 // Set experimental values for main thread hangs:
296 // 128ms for transient hangs and 8192ms for permanent hangs
297 sMessageLoop->set_hang_timeouts(128, 8192);
298 } else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) {
299 messageLoop->set_thread_name("Gecko_Child");
300 messageLoop->set_hang_timeouts(128, 8192);
303 if (XRE_IsParentProcess() &&
304 !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) {
305 mozilla::UniquePtr<BrowserProcessSubThread> ioThread =
306 mozilla::MakeUnique<BrowserProcessSubThread>(
307 BrowserProcessSubThread::IO);
309 base::Thread::Options options;
310 options.message_loop_type = MessageLoop::TYPE_IO;
311 if (NS_WARN_IF(!ioThread->StartWithOptions(options))) {
312 return NS_ERROR_FAILURE;
315 sIOThread = ioThread.release();
318 // Establish the main thread here.
319 rv = nsThreadManager::get().Init();
320 if (NS_WARN_IF(NS_FAILED(rv))) {
321 return rv;
323 AUTO_PROFILER_INIT2;
325 // Set up the timer globals/timer thread
326 rv = nsTimerImpl::Startup();
327 if (NS_WARN_IF(NS_FAILED(rv))) {
328 return rv;
331 #ifndef ANDROID
332 // If the locale hasn't already been setup by our embedder,
333 // get us out of the "C" locale and into the system
334 if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) {
335 setlocale(LC_ALL, "");
337 #endif
339 nsDirectoryService::RealInit();
341 bool value;
343 if (aBinDirectory) {
344 rv = aBinDirectory->IsDirectory(&value);
346 if (NS_SUCCEEDED(rv) && value) {
347 nsDirectoryService::gService->SetCurrentProcessDirectory(aBinDirectory);
351 if (aAppFileLocationProvider) {
352 rv = nsDirectoryService::gService->RegisterProvider(
353 aAppFileLocationProvider);
354 if (NS_FAILED(rv)) {
355 return rv;
359 nsCOMPtr<nsIFile> xpcomLib;
360 nsDirectoryService::gService->Get(NS_GRE_BIN_DIR, NS_GET_IID(nsIFile),
361 getter_AddRefs(xpcomLib));
362 MOZ_ASSERT(xpcomLib);
364 // set gGREBinPath
365 nsAutoString path;
366 xpcomLib->GetPath(path);
367 gGREBinPath = ToNewUnicode(path);
369 xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
370 nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
372 if (!mozilla::Omnijar::IsInitialized()) {
373 // If you added a new process type that uses NS_InitXPCOM, and you're
374 // *sure* you don't want NS_InitMinimalXPCOM: in addition to everything
375 // else you'll probably have to do, please add it to the case in
376 // GeckoChildProcessHost.cpp which sets the greomni/appomni flags.
377 MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsContentProcess());
378 mozilla::Omnijar::Init();
381 if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
382 #ifdef XP_WIN
383 CommandLine::Init(0, nullptr);
384 #else
385 nsCOMPtr<nsIFile> binaryFile;
386 nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
387 NS_GET_IID(nsIFile),
388 getter_AddRefs(binaryFile));
389 if (NS_WARN_IF(!binaryFile)) {
390 return NS_ERROR_FAILURE;
393 rv = binaryFile->AppendNative("nonexistent-executable"_ns);
394 if (NS_WARN_IF(NS_FAILED(rv))) {
395 return rv;
398 nsCString binaryPath;
399 rv = binaryFile->GetNativePath(binaryPath);
400 if (NS_WARN_IF(NS_FAILED(rv))) {
401 return rv;
404 static char const* const argv = {strdup(binaryPath.get())};
405 CommandLine::Init(1, &argv);
406 #endif
409 NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr,
410 "CompMgr not null at init");
412 // Create the Component/Service Manager
413 nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
414 NS_ADDREF(nsComponentManagerImpl::gComponentManager);
416 // Global cycle collector initialization.
417 if (!nsCycleCollector_init()) {
418 return NS_ERROR_UNEXPECTED;
421 // And start it up for this thread too.
422 nsCycleCollector_startup();
424 // Register ICU memory functions. This really shouldn't be necessary: the
425 // JS engine should do this on its own inside JS_Init, and memory-reporting
426 // code should call a JSAPI function to observe ICU memory usage. But we
427 // can't define the alloc/free functions in the JS engine, because it can't
428 // depend on the XPCOM-based memory reporting goop. So for now, we have
429 // this oddness.
430 mozilla::SetICUMemoryFunctions();
432 // Do the same for libogg.
433 ogg_set_mem_functions(
434 OggReporter::CountingMalloc, OggReporter::CountingCalloc,
435 OggReporter::CountingRealloc, OggReporter::CountingFree);
437 // Initialize the JS engine.
438 InitializeJS();
439 sInitializedJS = true;
441 rv = nsComponentManagerImpl::gComponentManager->Init();
442 if (NS_FAILED(rv)) {
443 NS_RELEASE(nsComponentManagerImpl::gComponentManager);
444 return rv;
447 if (aResult) {
448 NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
451 #ifdef MOZ_PHC
452 // This is the earliest possible moment we can start PHC while still being
453 // able to read prefs.
454 mozilla::InitPHCState();
455 #endif
457 // After autoreg, but before we actually instantiate any components,
458 // add any services listed in the "xpcom-directory-providers" category
459 // to the directory service.
460 nsDirectoryService::gService->RegisterCategoryProviders();
462 // Init mozilla::SharedThreadPool (which needs the service manager).
463 mozilla::SharedThreadPool::InitStatics();
465 mozilla::scache::StartupCache::GetSingleton();
466 mozilla::AvailableMemoryTracker::Init();
468 // Notify observers of xpcom autoregistration start
469 NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nullptr,
470 NS_XPCOM_STARTUP_OBSERVER_ID);
471 #ifdef XP_WIN
472 CreateAnonTempFileRemover();
473 #endif
475 // The memory reporter manager is up and running -- register our reporters.
476 RegisterStrongMemoryReporter(new ICUReporter());
477 RegisterStrongMemoryReporter(new OggReporter());
478 xpc::SelfHostedShmem::GetSingleton().InitMemoryReporter();
480 mozilla::Telemetry::Init();
482 mozilla::BackgroundHangMonitor::Startup();
484 const MessageLoop* const loop = MessageLoop::current();
485 sMainHangMonitor = new mozilla::BackgroundHangMonitor(
486 loop->thread_name().c_str(), loop->transient_hang_timeout(),
487 loop->permanent_hang_timeout());
489 mozilla::dom::JSExecutionManager::Initialize();
491 if (aInitJSContext) {
492 xpc::InitializeJSContext();
495 return NS_OK;
498 EXPORT_XPCOM_API(nsresult)
499 NS_InitMinimalXPCOM() {
500 NS_SetMainThread();
501 mozilla::TimeStamp::Startup();
502 NS_LogInit();
503 NS_InitAtomTable();
505 // We don't have the arguments by hand here. If logging has already been
506 // initialized by a previous call to LogModule::Init with the arguments
507 // passed, passing (0, nullptr) is alright here.
508 mozilla::LogModule::Init(0, nullptr);
510 GkRust_Init();
512 nsresult rv = nsThreadManager::get().Init();
513 if (NS_WARN_IF(NS_FAILED(rv))) {
514 return rv;
517 // Set up the timer globals/timer thread.
518 rv = nsTimerImpl::Startup();
519 if (NS_WARN_IF(NS_FAILED(rv))) {
520 return rv;
523 // Create the Component/Service Manager
524 nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
525 NS_ADDREF(nsComponentManagerImpl::gComponentManager);
527 rv = nsComponentManagerImpl::gComponentManager->Init();
528 if (NS_FAILED(rv)) {
529 NS_RELEASE(nsComponentManagerImpl::gComponentManager);
530 return rv;
533 // Global cycle collector initialization.
534 if (!nsCycleCollector_init()) {
535 return NS_ERROR_UNEXPECTED;
538 mozilla::SharedThreadPool::InitStatics();
539 mozilla::Telemetry::Init();
540 mozilla::BackgroundHangMonitor::Startup();
542 return NS_OK;
546 // NS_ShutdownXPCOM()
548 // The shutdown sequence for xpcom would be
550 // - Notify "xpcom-shutdown" for modules to release primary (root) references
551 // - Shutdown XPCOM timers
552 // - Notify "xpcom-shutdown-threads" for thread joins
553 // - Shutdown the event queues
554 // - Release the Global Service Manager
555 // - Release all service instances held by the global service manager
556 // - Release the Global Service Manager itself
557 // - Release the Component Manager
558 // - Release all factories cached by the Component Manager
559 // - Notify module loaders to shut down
560 // - Unload Libraries
561 // - Release Contractid Cache held by Component Manager
562 // - Release dll abstraction held by Component Manager
563 // - Release the Registry held by Component Manager
564 // - Finally, release the component manager itself
566 EXPORT_XPCOM_API(nsresult)
567 NS_ShutdownXPCOM(nsIServiceManager* aServMgr) {
568 return mozilla::ShutdownXPCOM(aServMgr);
571 namespace mozilla {
573 void SetICUMemoryFunctions() {
574 static bool sICUReporterInitialized = false;
575 if (!sICUReporterInitialized) {
576 if (!JS_SetICUMemoryFunctions(ICUReporter::Alloc, ICUReporter::Realloc,
577 ICUReporter::Free)) {
578 MOZ_CRASH("JS_SetICUMemoryFunctions failed.");
580 sICUReporterInitialized = true;
584 nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) {
585 // Make sure the hang monitor is enabled for shutdown.
586 BackgroundHangMonitor().NotifyActivity();
588 if (!NS_IsMainThread()) {
589 MOZ_CRASH("Shutdown on wrong thread");
592 // Notify observers of xpcom shutting down
594 // Block it so that the COMPtr will get deleted before we hit
595 // servicemanager shutdown
597 nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
598 if (NS_WARN_IF(!thread)) {
599 return NS_ERROR_UNEXPECTED;
602 mozilla::AppShutdown::AdvanceShutdownPhase(
603 mozilla::ShutdownPhase::XPCOMWillShutdown);
605 // We want the service manager to be the subject of notifications
606 nsCOMPtr<nsIServiceManager> mgr;
607 Unused << NS_GetServiceManager(getter_AddRefs(mgr));
608 MOZ_DIAGNOSTIC_ASSERT(mgr != nullptr, "Service manager not present!");
609 mozilla::AppShutdown::AdvanceShutdownPhase(
610 mozilla::ShutdownPhase::XPCOMShutdown, nullptr, do_QueryInterface(mgr));
612 // This must happen after the shutdown of media and widgets, which
613 // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
614 gfxPlatform::ShutdownLayersIPC();
616 mozilla::AppShutdown::AdvanceShutdownPhase(
617 mozilla::ShutdownPhase::XPCOMShutdownThreads);
618 #ifdef DEBUG
619 // Prime an assertion at ThreadEventTarget::Dispatch to avoid late
620 // dispatches to non main-thread threads.
621 ThreadEventTarget::XPCOMShutdownThreadsNotificationFinished();
622 #endif
624 // Shutdown the timer thread and all timers that might still be alive
625 nsTimerImpl::Shutdown();
627 // Have an extra round of processing after the timers went away.
628 NS_ProcessPendingEvents(thread);
630 // Shutdown all remaining threads. This method does not return until
631 // all threads created using the thread manager (with the exception of
632 // the main thread) have exited.
633 nsThreadManager::get().ShutdownNonMainThreads();
635 RefPtr<nsObserverService> observerService;
636 CallGetService("@mozilla.org/observer-service;1",
637 (nsObserverService**)getter_AddRefs(observerService));
638 if (observerService) {
639 observerService->Shutdown();
642 #ifdef NS_FREE_PERMANENT_DATA
643 // In leak-checking / ASAN / etc. builds, shut down the Servo thread-pool,
644 // which will wait for all the work to be done. For other builds, we don't
645 // really want to wait on shutdown for possibly slow tasks.
646 Servo_ShutdownThreadPool();
647 #endif
649 // XPCOMShutdownFinal is the default phase for ClearOnShutdown.
650 // This AdvanceShutdownPhase will thus free most ClearOnShutdown()'ed
651 // smart pointers. Some destructors may fire extra main thread runnables
652 // that will be processed inside AdvanceShutdownPhase.
653 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::XPCOMShutdownFinal);
655 // Shutdown the main thread, processing our very last round of events, and
656 // then mark that we've finished main thread event processing.
657 nsThreadManager::get().ShutdownMainThread();
658 gXPCOMMainThreadEventsAreDoomed = true;
660 BackgroundHangMonitor().NotifyActivity();
662 mozilla::dom::JSExecutionManager::Shutdown();
665 // XPCOM is officially in shutdown mode NOW
666 // Set this only after the observers have been notified as this
667 // will cause servicemanager to become inaccessible.
668 mozilla::services::Shutdown();
670 // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
671 // here again:
672 NS_IF_RELEASE(aServMgr);
674 // Shutdown global servicemanager
675 if (nsComponentManagerImpl::gComponentManager) {
676 nsComponentManagerImpl::gComponentManager->FreeServices();
679 // Remove the remaining main thread representations
680 nsThreadManager::get().ReleaseMainThread();
681 AbstractThread::ShutdownMainThread();
683 // Release the directory service
684 nsDirectoryService::gService = nullptr;
686 free(gGREBinPath);
687 gGREBinPath = nullptr;
689 // FIXME: This can cause harmless writes from sqlite committing
690 // log files. We have to ignore them before we can move
691 // the mozilla::PoisonWrite call before this point. See bug
692 // 834945 for the details.
693 mozJSModuleLoader::UnloadLoaders();
695 // Clear the profiler's JS context before cycle collection. The profiler will
696 // notify the JS engine that it can let go of any data it's holding on to for
697 // profiling purposes.
698 PROFILER_CLEAR_JS_CONTEXT();
700 bool shutdownCollect;
701 #ifdef NS_FREE_PERMANENT_DATA
702 shutdownCollect = true;
703 #else
704 shutdownCollect = !!PR_GetEnv("MOZ_CC_RUN_DURING_SHUTDOWN");
705 #endif
706 nsCycleCollector_shutdown(shutdownCollect);
708 // There can be code trying to refer to global objects during the final cc
709 // shutdown. This is the phase for such global objects to correctly release.
710 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::CCPostLastCycleCollection);
712 mozilla::scache::StartupCache::DeleteSingleton();
713 mozilla::ScriptPreloader::DeleteSingleton();
715 PROFILER_MARKER_UNTYPED("Shutdown xpcom", OTHER);
717 // Shutdown xpcom. This will release all loaders and cause others holding
718 // a refcount to the component manager to release it.
719 if (nsComponentManagerImpl::gComponentManager) {
720 DebugOnly<nsresult> rv =
721 (nsComponentManagerImpl::gComponentManager)->Shutdown();
722 NS_ASSERTION(NS_SUCCEEDED(rv.value), "Component Manager shutdown failed.");
723 } else {
724 NS_WARNING("Component Manager was never created ...");
727 if (sInitializedJS) {
728 // Shut down the JS engine.
729 JS_ShutDown();
730 sInitializedJS = false;
733 mozilla::ScriptPreloader::DeleteCacheDataSingleton();
735 // Release shared memory which might be borrowed by the JS engine.
736 xpc::SelfHostedShmem::Shutdown();
738 // After all threads have been joined and the component manager has been shut
739 // down, any remaining objects that could be holding NSS resources (should)
740 // have been released, so we can safely shut down NSS.
741 if (NSS_IsInitialized()) {
742 nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
743 if (NSS_Shutdown() != SECSuccess) {
744 // If you're seeing this crash and/or warning, some NSS resources are
745 // still in use (see bugs 1417680 and 1230312). Set the environment
746 // variable 'MOZ_IGNORE_NSS_SHUTDOWN_LEAKS' to some value to ignore this.
747 // Also, if leak checking is enabled, report this as a fake leak instead
748 // of crashing.
749 #if defined(DEBUG) && !defined(ANDROID)
750 if (!getenv("MOZ_IGNORE_NSS_SHUTDOWN_LEAKS") &&
751 !getenv("XPCOM_MEM_BLOAT_LOG") && !getenv("XPCOM_MEM_LEAK_LOG") &&
752 !getenv("XPCOM_MEM_REFCNT_LOG") && !getenv("XPCOM_MEM_COMPTR_LOG")) {
753 MOZ_CRASH("NSS_Shutdown failed");
754 } else {
755 # ifdef NS_BUILD_REFCNT_LOGGING
756 // Create a fake leak.
757 NS_LogCtor((void*)0x100, "NSSShutdownFailed", 100);
758 # endif // NS_BUILD_REFCNT_LOGGING
759 NS_WARNING("NSS_Shutdown failed");
761 #else
762 NS_WARNING("NSS_Shutdown failed");
763 #endif // defined(DEBUG) && !defined(ANDROID)
767 // Finally, release the component manager last because it unloads the
768 // libraries:
769 if (nsComponentManagerImpl::gComponentManager) {
770 nsrefcnt cnt;
771 NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
772 NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown.");
774 nsComponentManagerImpl::gComponentManager = nullptr;
775 nsCategoryManager::Destroy();
777 nsLanguageAtomService::Shutdown();
779 GkRust_Shutdown();
781 #ifdef NS_FREE_PERMANENT_DATA
782 // As we do shutdown Servo only in leak-checking builds, there may still
783 // be async parse tasks going on in the Servo thread-pool in other builds.
784 // CSS parsing heavily uses the atom table, so we can safely drop it only
785 // if Servo has been stopped, too.
786 NS_ShutdownAtomTable();
787 #endif
789 NS_IF_RELEASE(gDebug);
791 delete sIOThread;
792 sIOThread = nullptr;
794 delete sMessageLoop;
795 sMessageLoop = nullptr;
797 mozilla::TaskController::Shutdown();
799 if (sCommandLineWasInitialized) {
800 CommandLine::Terminate();
801 sCommandLineWasInitialized = false;
804 delete sExitManager;
805 sExitManager = nullptr;
807 Omnijar::CleanUp();
809 BackgroundHangMonitor::Shutdown();
811 delete sMainHangMonitor;
812 sMainHangMonitor = nullptr;
814 NS_LogTerm();
816 return NS_OK;
819 } // namespace mozilla