Bug 1919083 - [ci] Enable os-integration variant for more suites, r=jmaher
[gecko.git] / xpcom / build / XPCOMInit.cpp
blob22185cd8bcb27c7087e00b922a6bb162f3a8774b
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/dom/SharedScriptCache.h"
34 #include "mozilla/SharedStyleSheetCache.h"
35 #include "mozilla/layers/ImageBridgeChild.h"
36 #include "mozilla/layers/CompositorBridgeParent.h"
38 #include "prlink.h"
40 #include "nsCycleCollector.h"
41 #include "nsObserverService.h"
43 #include "nsDebugImpl.h"
44 #include "nsSystemInfo.h"
46 #include "nsComponentManager.h"
47 #include "nsCategoryManagerUtils.h"
48 #include "nsIServiceManager.h"
50 #include "nsThreadManager.h"
51 #include "nsThreadPool.h"
53 #include "nsTimerImpl.h"
54 #include "TimerThread.h"
56 #include "nsThread.h"
57 #include "nsVersionComparatorImpl.h"
59 #include "nsIFile.h"
60 #include "nsLocalFile.h"
61 #include "nsDirectoryService.h"
62 #include "nsDirectoryServiceDefs.h"
63 #include "nsCategoryManager.h"
64 #include "nsMultiplexInputStream.h"
66 #include "nsAtomTable.h"
67 #include "nsISupportsImpl.h"
68 #include "nsLanguageAtomService.h"
70 #include "nsSystemInfo.h"
71 #include "nsMemoryReporterManager.h"
72 #include "nss.h"
73 #include "nsNSSComponent.h"
75 #include <locale.h>
76 #include "mozilla/Services.h"
77 #include "mozilla/Omnijar.h"
78 #include "mozilla/ScriptPreloader.h"
79 #include "mozilla/Telemetry.h"
80 #include "mozilla/BackgroundHangMonitor.h"
82 #include "mozilla/PoisonIOInterposer.h"
83 #include "mozilla/LateWriteChecks.h"
85 #include "mozilla/scache/StartupCache.h"
87 #include "base/at_exit.h"
88 #include "base/command_line.h"
89 #include "base/message_loop.h"
91 #include "mozilla/ipc/IOThread.h"
92 #include "mozilla/AvailableMemoryTracker.h"
93 #include "mozilla/ClearOnShutdown.h"
94 #include "mozilla/CountingAllocatorBase.h"
95 #ifdef MOZ_PHC
96 # include "mozilla/PHCManager.h"
97 #endif
98 #include "mozilla/UniquePtr.h"
99 #include "mozilla/ServoStyleConsts.h"
101 #include "mozilla/ipc/GeckoChildProcessHost.h"
103 #include "ogg/ogg.h"
105 #include "GeckoProfiler.h"
106 #include "ProfilerControl.h"
108 #include "jsapi.h"
109 #include "js/Initialization.h"
110 #include "js/Prefs.h"
111 #include "mozilla/StaticPrefs_javascript.h"
112 #include "XPCSelfHostedShmem.h"
114 #include "gfxPlatform.h"
116 using base::AtExitManager;
117 using mozilla::ipc::IOThreadParent;
119 // From toolkit/library/rust/lib.rs
120 extern "C" void GkRust_Init();
121 extern "C" void GkRust_Shutdown();
123 namespace {
125 static AtExitManager* sExitManager;
126 static MessageLoop* sMessageLoop;
127 static bool sCommandLineWasInitialized;
128 static IOThreadParent* sIOThread;
129 static mozilla::BackgroundHangMonitor* sMainHangMonitor;
131 } /* anonymous namespace */
133 // Registry Factory creation function defined in nsRegistry.cpp
134 // We hook into this function locally to create and register the registry
135 // Since noone outside xpcom needs to know about this and nsRegistry.cpp
136 // does not have a local include file, we are putting this definition
137 // here rather than in nsIRegistry.h
138 extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
139 extern nsresult NS_CategoryManagerGetFactory(nsIFactory**);
141 #ifdef XP_WIN
142 extern nsresult CreateAnonTempFileRemover();
143 #endif
145 nsresult nsThreadManagerGetSingleton(const nsIID& aIID, void** aInstancePtr) {
146 NS_ASSERTION(aInstancePtr, "null outptr");
147 return nsThreadManager::get().QueryInterface(aIID, aInstancePtr);
150 nsresult nsLocalFileConstructor(const nsIID& aIID, void** aInstancePtr) {
151 return nsLocalFile::nsLocalFileConstructor(aIID, aInstancePtr);
154 nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = nullptr;
155 bool gXPCOMShuttingDown = false;
156 bool gXPCOMMainThreadEventsAreDoomed = false;
157 char16_t* gGREBinPath = nullptr;
159 // gDebug will be freed during shutdown.
160 static nsIDebug2* gDebug = nullptr;
162 EXPORT_XPCOM_API(nsresult)
163 NS_GetDebug(nsIDebug2** aResult) {
164 return nsDebugImpl::Create(NS_GET_IID(nsIDebug2), (void**)aResult);
167 class ICUReporter final : public nsIMemoryReporter,
168 public mozilla::CountingAllocatorBase<ICUReporter> {
169 public:
170 NS_DECL_ISUPPORTS
172 static void* Alloc(const void*, size_t aSize) {
173 void* result = CountingMalloc(aSize);
174 if (result == nullptr) {
175 MOZ_CRASH("Ran out of memory while allocating for ICU");
177 return result;
180 static void* Realloc(const void*, void* aPtr, size_t aSize) {
181 void* result = CountingRealloc(aPtr, aSize);
182 if (result == nullptr) {
183 MOZ_CRASH("Ran out of memory while reallocating for ICU");
185 return result;
188 static void Free(const void*, void* aPtr) { return CountingFree(aPtr); }
190 private:
191 NS_IMETHOD
192 CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
193 bool aAnonymize) override {
194 MOZ_COLLECT_REPORT(
195 "explicit/icu", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
196 "Memory used by ICU, a Unicode and globalization support library.");
198 return NS_OK;
201 ~ICUReporter() = default;
204 NS_IMPL_ISUPPORTS(ICUReporter, nsIMemoryReporter)
206 class OggReporter final : public nsIMemoryReporter,
207 public mozilla::CountingAllocatorBase<OggReporter> {
208 public:
209 NS_DECL_ISUPPORTS
211 private:
212 NS_IMETHOD
213 CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
214 bool aAnonymize) override {
215 MOZ_COLLECT_REPORT(
216 "explicit/media/libogg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
217 "Memory allocated through libogg for Ogg, and related media "
218 "files.");
220 return NS_OK;
223 ~OggReporter() = default;
226 NS_IMPL_ISUPPORTS(OggReporter, nsIMemoryReporter)
228 static bool sInitializedJS = false;
230 static void InitializeJS() {
231 #if defined(ENABLE_WASM_SIMD) && \
232 (defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86))
233 // Update static engine preferences, such as AVX, before
234 // `JS_InitWithFailureDiagnostic` is called.
235 JS::SetAVXEnabled(mozilla::StaticPrefs::javascript_options_wasm_simd_avx());
236 #endif
238 if (XRE_IsParentProcess() &&
239 mozilla::StaticPrefs::javascript_options_main_process_disable_jit()) {
240 JS::DisableJitBackend();
243 // Set all JS::Prefs.
244 SET_JS_PREFS_FROM_BROWSER_PREFS;
246 const char* jsInitFailureReason = JS_InitWithFailureDiagnostic();
247 if (jsInitFailureReason) {
248 MOZ_CRASH_UNSAFE(jsInitFailureReason);
252 #define XPCOM_INIT_FATAL(message, res) \
253 if (XRE_IsParentProcess()) { \
254 return res; \
256 MOZ_CRASH(message);
258 // Note that on OSX, aBinDirectory will point to .app/Contents/Resources/browser
259 EXPORT_XPCOM_API(nsresult)
260 NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
261 nsIDirectoryServiceProvider* aAppFileLocationProvider,
262 bool aInitJSContext) {
263 static bool sInitialized = false;
264 if (sInitialized) {
265 XPCOM_INIT_FATAL("!sInitialized", NS_ERROR_FAILURE)
268 sInitialized = true;
270 NS_LogInit();
272 NS_InitAtomTable();
274 // We don't have the arguments by hand here. If logging has already been
275 // initialized by a previous call to LogModule::Init with the arguments
276 // passed, passing (0, nullptr) is alright here.
277 mozilla::LogModule::Init(0, nullptr);
279 GkRust_Init();
281 nsresult rv = NS_OK;
283 // We are not shutting down
284 gXPCOMShuttingDown = false;
286 #ifdef XP_UNIX
287 // Discover the current value of the umask, and save it where
288 // nsSystemInfo::Init can retrieve it when necessary. There is no way
289 // to read the umask without changing it, and the setting is process-
290 // global, so this must be done while we are still single-threaded; the
291 // nsSystemInfo object is typically created much later, when some piece
292 // of chrome JS wants it. The system call is specified as unable to fail.
293 nsSystemInfo::gUserUmask = ::umask(0777);
294 ::umask(nsSystemInfo::gUserUmask);
295 #endif
297 // Set up chromium libs
298 NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
300 if (!AtExitManager::AlreadyRegistered()) {
301 sExitManager = new AtExitManager();
304 MessageLoop* messageLoop = MessageLoop::current();
305 if (!messageLoop) {
306 sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT);
307 sMessageLoop->set_thread_name("Gecko");
308 // Set experimental values for main thread hangs:
309 // 128ms for transient hangs and 8192ms for permanent hangs
310 sMessageLoop->set_hang_timeouts(128, 8192);
311 } else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) {
312 messageLoop->set_thread_name("Gecko_Child");
313 messageLoop->set_hang_timeouts(128, 8192);
316 // Start the IPC I/O thread in the parent process. We'll have already started
317 // the IPC I/O thread if we're in a content process.
318 if (XRE_IsParentProcess()) {
319 sIOThread = new IOThreadParent();
321 MOZ_ASSERT(mozilla::ipc::IOThread::Get(), "An IOThread has been started");
323 // Establish the main thread here.
324 rv = nsThreadManager::get().Init();
325 if (NS_WARN_IF(NS_FAILED(rv))) {
326 XPCOM_INIT_FATAL("nsThreadManager::get().Init()", rv)
329 // Initialise the profiler
330 AUTO_PROFILER_INIT2;
332 // Set up the timer globals/timer thread
333 rv = nsTimerImpl::Startup();
334 if (NS_WARN_IF(NS_FAILED(rv))) {
335 XPCOM_INIT_FATAL("nsTimerImpl::Startup()", rv)
338 #ifndef ANDROID
339 // If the locale hasn't already been setup by our embedder,
340 // get us out of the "C" locale and into the system
341 if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) {
342 setlocale(LC_ALL, "");
344 #endif
346 nsDirectoryService::RealInit();
348 bool value;
350 if (aBinDirectory) {
351 rv = aBinDirectory->IsDirectory(&value);
353 if (NS_SUCCEEDED(rv) && value) {
354 nsDirectoryService::gService->SetCurrentProcessDirectory(aBinDirectory);
358 if (aAppFileLocationProvider) {
359 rv = nsDirectoryService::gService->RegisterProvider(
360 aAppFileLocationProvider);
361 if (NS_FAILED(rv)) {
362 XPCOM_INIT_FATAL("nsDirectoryService::gService->RegisterProvider()", rv)
366 nsCOMPtr<nsIFile> xpcomLib;
367 nsDirectoryService::gService->Get(NS_GRE_BIN_DIR, NS_GET_IID(nsIFile),
368 getter_AddRefs(xpcomLib));
369 MOZ_ASSERT(xpcomLib);
371 // set gGREBinPath
372 nsAutoString path;
373 xpcomLib->GetPath(path);
374 gGREBinPath = ToNewUnicode(path);
376 xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
377 nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
379 if (!mozilla::Omnijar::IsInitialized()) {
380 // If you added a new process type that uses NS_InitXPCOM, and you're
381 // *sure* you don't want NS_InitMinimalXPCOM: in addition to everything
382 // else you'll probably have to do, please add it to the case in
383 // GeckoChildProcessHost.cpp which sets the greomni/appomni flags.
384 MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsContentProcess());
386 // Note that the Omnijar::FallibleInit does not fail but returns NS_OK if
387 // the file is not found at all, as this is an expected possible way of
388 // running with an unpacked modules directory.
389 nsresult rv = mozilla::Omnijar::FallibleInit();
390 if (NS_FAILED(rv)) {
391 XPCOM_INIT_FATAL("Omnijar::Init()", NS_ERROR_OMNIJAR_CORRUPT)
395 if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
396 #ifdef XP_WIN
397 CommandLine::Init(0, nullptr);
398 #else
399 nsCOMPtr<nsIFile> binaryFile;
400 nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
401 NS_GET_IID(nsIFile),
402 getter_AddRefs(binaryFile));
403 if (NS_WARN_IF(!binaryFile)) {
404 XPCOM_INIT_FATAL("!binaryFile", NS_ERROR_FAILURE)
407 rv = binaryFile->AppendNative("nonexistent-executable"_ns);
408 if (NS_WARN_IF(NS_FAILED(rv))) {
409 XPCOM_INIT_FATAL("binaryFile->AppendNative()", rv)
412 nsCString binaryPath;
413 rv = binaryFile->GetNativePath(binaryPath);
414 if (NS_WARN_IF(NS_FAILED(rv))) {
415 XPCOM_INIT_FATAL("binaryFile->GetNativePath", rv)
418 static char const* const argv = {strdup(binaryPath.get())};
419 CommandLine::Init(1, &argv);
420 #endif
423 NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr,
424 "CompMgr not null at init");
426 // Create the Component/Service Manager
427 nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
428 NS_ADDREF(nsComponentManagerImpl::gComponentManager);
430 // Global cycle collector initialization.
431 if (!nsCycleCollector_init()) {
432 XPCOM_INIT_FATAL("nsCycleCollector_init()", NS_ERROR_UNEXPECTED)
435 // And start it up for this thread too.
436 nsCycleCollector_startup();
438 // Register ICU memory functions. This really shouldn't be necessary: the
439 // JS engine should do this on its own inside JS_Init, and memory-reporting
440 // code should call a JSAPI function to observe ICU memory usage. But we
441 // can't define the alloc/free functions in the JS engine, because it can't
442 // depend on the XPCOM-based memory reporting goop. So for now, we have
443 // this oddness.
444 mozilla::SetICUMemoryFunctions();
446 // Do the same for libogg.
447 ogg_set_mem_functions(
448 OggReporter::CountingMalloc, OggReporter::CountingCalloc,
449 OggReporter::CountingRealloc, OggReporter::CountingFree);
451 // Initialize the JS engine.
452 InitializeJS();
453 sInitializedJS = true;
455 rv = nsComponentManagerImpl::gComponentManager->Init();
456 if (NS_FAILED(rv)) {
457 NS_RELEASE(nsComponentManagerImpl::gComponentManager);
458 XPCOM_INIT_FATAL("gComponentManager->Init()", rv)
461 if (aResult) {
462 NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
465 #ifdef MOZ_PHC
466 // This is the earliest possible moment we can start PHC while still being
467 // able to read prefs.
468 mozilla::InitPHCState();
469 #endif
471 // After autoreg, but before we actually instantiate any components,
472 // add any services listed in the "xpcom-directory-providers" category
473 // to the directory service.
474 nsDirectoryService::gService->RegisterCategoryProviders();
476 // Now that both the profiler and directory services have been started
477 // we can find the download directory, where the profiler can write
478 // profiles if necessary
479 profiler_lookup_async_signal_dump_directory();
481 // Init mozilla::SharedThreadPool (which needs the service manager).
482 mozilla::SharedThreadPool::InitStatics();
484 mozilla::scache::StartupCache::GetSingleton();
485 mozilla::AvailableMemoryTracker::Init();
487 // Notify observers of xpcom autoregistration start
488 NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nullptr,
489 NS_XPCOM_STARTUP_OBSERVER_ID);
490 #ifdef XP_WIN
491 CreateAnonTempFileRemover();
492 #endif
494 // The memory reporter manager is up and running -- register our reporters.
495 RegisterStrongMemoryReporter(new ICUReporter());
496 RegisterStrongMemoryReporter(new OggReporter());
497 xpc::SelfHostedShmem::GetSingleton().InitMemoryReporter();
499 mozilla::Telemetry::Init();
501 mozilla::BackgroundHangMonitor::Startup();
503 const MessageLoop* const loop = MessageLoop::current();
504 sMainHangMonitor = new mozilla::BackgroundHangMonitor(
505 loop->thread_name().c_str(), loop->transient_hang_timeout(),
506 loop->permanent_hang_timeout());
508 mozilla::dom::JSExecutionManager::Initialize();
510 if (aInitJSContext) {
511 xpc::InitializeJSContext();
514 return NS_OK;
517 #undef XPCOM_INIT_FATAL
519 EXPORT_XPCOM_API(nsresult)
520 NS_InitMinimalXPCOM() {
521 NS_SetMainThread();
522 mozilla::TimeStamp::Startup();
523 NS_LogInit();
524 NS_InitAtomTable();
526 // We don't have the arguments by hand here. If logging has already been
527 // initialized by a previous call to LogModule::Init with the arguments
528 // passed, passing (0, nullptr) is alright here.
529 mozilla::LogModule::Init(0, nullptr);
531 GkRust_Init();
533 nsresult rv = nsThreadManager::get().Init();
534 if (NS_WARN_IF(NS_FAILED(rv))) {
535 return rv;
538 // Set up the timer globals/timer thread.
539 rv = nsTimerImpl::Startup();
540 if (NS_WARN_IF(NS_FAILED(rv))) {
541 return rv;
544 // Create the Component/Service Manager
545 nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
546 NS_ADDREF(nsComponentManagerImpl::gComponentManager);
548 rv = nsComponentManagerImpl::gComponentManager->Init();
549 if (NS_FAILED(rv)) {
550 NS_RELEASE(nsComponentManagerImpl::gComponentManager);
551 return rv;
554 // Global cycle collector initialization.
555 if (!nsCycleCollector_init()) {
556 return NS_ERROR_UNEXPECTED;
559 mozilla::SharedThreadPool::InitStatics();
560 mozilla::Telemetry::Init();
561 mozilla::BackgroundHangMonitor::Startup();
563 return NS_OK;
567 // NS_ShutdownXPCOM()
569 // The shutdown sequence for xpcom would be
571 // - Notify "xpcom-shutdown" for modules to release primary (root) references
572 // - Shutdown XPCOM timers
573 // - Notify "xpcom-shutdown-threads" for thread joins
574 // - Shutdown the event queues
575 // - Release the Global Service Manager
576 // - Release all service instances held by the global service manager
577 // - Release the Global Service Manager itself
578 // - Release the Component Manager
579 // - Release all factories cached by the Component Manager
580 // - Notify module loaders to shut down
581 // - Unload Libraries
582 // - Release Contractid Cache held by Component Manager
583 // - Release dll abstraction held by Component Manager
584 // - Release the Registry held by Component Manager
585 // - Finally, release the component manager itself
587 EXPORT_XPCOM_API(nsresult)
588 NS_ShutdownXPCOM(nsIServiceManager* aServMgr) {
589 return mozilla::ShutdownXPCOM(aServMgr);
592 namespace mozilla {
594 void SetICUMemoryFunctions() {
595 static bool sICUReporterInitialized = false;
596 if (!sICUReporterInitialized) {
597 if (!JS_SetICUMemoryFunctions(ICUReporter::Alloc, ICUReporter::Realloc,
598 ICUReporter::Free)) {
599 MOZ_CRASH("JS_SetICUMemoryFunctions failed.");
601 sICUReporterInitialized = true;
605 nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) {
606 // Make sure the hang monitor is enabled for shutdown.
607 BackgroundHangMonitor().NotifyActivity();
609 if (!NS_IsMainThread()) {
610 MOZ_CRASH("Shutdown on wrong thread");
613 // Notify observers of xpcom shutting down
615 // Block it so that the COMPtr will get deleted before we hit
616 // servicemanager shutdown
618 nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
619 if (NS_WARN_IF(!thread)) {
620 return NS_ERROR_UNEXPECTED;
623 mozilla::AppShutdown::AdvanceShutdownPhase(
624 mozilla::ShutdownPhase::XPCOMWillShutdown);
626 // We want the service manager to be the subject of notifications
627 nsCOMPtr<nsIServiceManager> mgr;
628 Unused << NS_GetServiceManager(getter_AddRefs(mgr));
629 MOZ_DIAGNOSTIC_ASSERT(mgr != nullptr, "Service manager not present!");
630 mozilla::AppShutdown::AdvanceShutdownPhase(
631 mozilla::ShutdownPhase::XPCOMShutdown, nullptr, do_QueryInterface(mgr));
633 // This must happen after the shutdown of media and widgets, which
634 // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
635 gfxPlatform::ShutdownLayersIPC();
637 mozilla::AppShutdown::AdvanceShutdownPhase(
638 mozilla::ShutdownPhase::XPCOMShutdownThreads);
639 #ifdef DEBUG
640 // Prime an assertion at ThreadEventTarget::Dispatch to avoid late
641 // dispatches to non main-thread threads.
642 ThreadEventTarget::XPCOMShutdownThreadsNotificationFinished();
643 #endif
645 // Shutdown the timer thread and all timers that might still be alive
646 nsTimerImpl::Shutdown();
648 // Have an extra round of processing after the timers went away.
649 NS_ProcessPendingEvents(thread);
651 // Shutdown all remaining threads. This method does not return until
652 // all threads created using the thread manager (with the exception of
653 // the main thread) have exited.
654 nsThreadManager::get().ShutdownNonMainThreads();
656 RefPtr<nsObserverService> observerService;
657 CallGetService("@mozilla.org/observer-service;1",
658 (nsObserverService**)getter_AddRefs(observerService));
659 if (observerService) {
660 observerService->Shutdown();
663 #ifdef NS_FREE_PERMANENT_DATA
664 // In leak-checking / ASAN / etc. builds, shut down the Servo thread-pool,
665 // which will wait for all the work to be done. For other builds, we don't
666 // really want to wait on shutdown for possibly slow tasks.
667 Servo_ShutdownThreadPool();
668 #endif
670 // XPCOMShutdownFinal is the default phase for ClearOnShutdown.
671 // This AdvanceShutdownPhase will thus free most ClearOnShutdown()'ed
672 // smart pointers. Some destructors may fire extra main thread runnables
673 // that will be processed inside AdvanceShutdownPhase.
674 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::XPCOMShutdownFinal);
676 // Shutdown the main thread, processing our very last round of events, and
677 // then mark that we've finished main thread event processing.
678 nsThreadManager::get().ShutdownMainThread();
679 gXPCOMMainThreadEventsAreDoomed = true;
681 BackgroundHangMonitor().NotifyActivity();
683 mozilla::dom::JSExecutionManager::Shutdown();
686 // XPCOM is officially in shutdown mode NOW
687 // Set this only after the observers have been notified as this
688 // will cause servicemanager to become inaccessible.
689 mozilla::services::Shutdown();
691 // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
692 // here again:
693 NS_IF_RELEASE(aServMgr);
695 // Shutdown global servicemanager
696 if (nsComponentManagerImpl::gComponentManager) {
697 nsComponentManagerImpl::gComponentManager->FreeServices();
700 // Remove the remaining main thread representations
701 nsThreadManager::get().ReleaseMainThread();
702 AbstractThread::ShutdownMainThread();
704 // Release the directory service
705 nsDirectoryService::gService = nullptr;
707 free(gGREBinPath);
708 gGREBinPath = nullptr;
710 // FIXME: This can cause harmless writes from sqlite committing
711 // log files. We have to ignore them before we can move
712 // the mozilla::PoisonWrite call before this point. See bug
713 // 834945 for the details.
714 mozJSModuleLoader::UnloadLoaders();
716 // Clear the profiler's JS context before cycle collection. The profiler will
717 // notify the JS engine that it can let go of any data it's holding on to for
718 // profiling purposes.
719 PROFILER_CLEAR_JS_CONTEXT();
721 bool shutdownCollect;
722 #ifdef NS_FREE_PERMANENT_DATA
723 shutdownCollect = true;
724 #else
725 shutdownCollect = !!PR_GetEnv("MOZ_CC_RUN_DURING_SHUTDOWN");
726 #endif
727 nsCycleCollector_shutdown(shutdownCollect);
729 // There can be code trying to refer to global objects during the final cc
730 // shutdown. This is the phase for such global objects to correctly release.
731 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::CCPostLastCycleCollection);
733 mozilla::scache::StartupCache::DeleteSingleton();
734 mozilla::ScriptPreloader::DeleteSingleton();
736 PROFILER_MARKER_UNTYPED("Shutdown xpcom", OTHER);
738 // Shutdown xpcom. This will release all loaders and cause others holding
739 // a refcount to the component manager to release it.
740 if (nsComponentManagerImpl::gComponentManager) {
741 DebugOnly<nsresult> rv =
742 (nsComponentManagerImpl::gComponentManager)->Shutdown();
743 NS_ASSERTION(NS_SUCCEEDED(rv.value), "Component Manager shutdown failed.");
744 } else {
745 NS_WARNING("Component Manager was never created ...");
748 if (sInitializedJS) {
749 // Shut down the JS engine.
750 JS_ShutDown();
751 sInitializedJS = false;
754 mozilla::ScriptPreloader::DeleteCacheDataSingleton();
756 mozilla::dom::SharedScriptCache::DeleteSingleton();
757 mozilla::SharedStyleSheetCache::DeleteSingleton();
759 // Release shared memory which might be borrowed by the JS engine.
760 xpc::SelfHostedShmem::Shutdown();
762 // After all threads have been joined and the component manager has been shut
763 // down, any remaining objects that could be holding NSS resources (should)
764 // have been released, so we can safely shut down NSS.
765 if (NSS_IsInitialized()) {
766 nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
767 if (NSS_Shutdown() != SECSuccess) {
768 // If you're seeing this crash and/or warning, some NSS resources are
769 // still in use (see bugs 1417680 and 1230312). Set the environment
770 // variable 'MOZ_IGNORE_NSS_SHUTDOWN_LEAKS' to some value to ignore this.
771 // Also, if leak checking is enabled, report this as a fake leak instead
772 // of crashing.
773 #if defined(DEBUG) && !defined(ANDROID)
774 if (!getenv("MOZ_IGNORE_NSS_SHUTDOWN_LEAKS") &&
775 !getenv("XPCOM_MEM_BLOAT_LOG") && !getenv("XPCOM_MEM_LEAK_LOG") &&
776 !getenv("XPCOM_MEM_REFCNT_LOG") && !getenv("XPCOM_MEM_COMPTR_LOG")) {
777 MOZ_CRASH("NSS_Shutdown failed");
778 } else {
779 # ifdef NS_BUILD_REFCNT_LOGGING
780 // Create a fake leak.
781 NS_LogCtor((void*)0x100, "NSSShutdownFailed", 100);
782 # endif // NS_BUILD_REFCNT_LOGGING
783 NS_WARNING("NSS_Shutdown failed");
785 #else
786 NS_WARNING("NSS_Shutdown failed");
787 #endif // defined(DEBUG) && !defined(ANDROID)
791 // Finally, release the component manager last because it unloads the
792 // libraries:
793 if (nsComponentManagerImpl::gComponentManager) {
794 nsrefcnt cnt;
795 NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
796 NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown.");
798 nsComponentManagerImpl::gComponentManager = nullptr;
799 nsCategoryManager::Destroy();
801 nsLanguageAtomService::Shutdown();
803 GkRust_Shutdown();
805 #ifdef NS_FREE_PERMANENT_DATA
806 // As we do shutdown Servo only in leak-checking builds, there may still
807 // be async parse tasks going on in the Servo thread-pool in other builds.
808 // CSS parsing heavily uses the atom table, so we can safely drop it only
809 // if Servo has been stopped, too.
810 NS_ShutdownAtomTable();
811 #endif
813 NS_IF_RELEASE(gDebug);
815 delete sIOThread;
816 sIOThread = nullptr;
818 delete sMessageLoop;
819 sMessageLoop = nullptr;
821 mozilla::TaskController::Shutdown();
823 if (sCommandLineWasInitialized) {
824 CommandLine::Terminate();
825 sCommandLineWasInitialized = false;
828 delete sExitManager;
829 sExitManager = nullptr;
831 Omnijar::CleanUp();
833 BackgroundHangMonitor::Shutdown();
835 delete sMainHangMonitor;
836 sMainHangMonitor = nullptr;
838 NS_LogTerm();
840 return NS_OK;
843 } // namespace mozilla