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"
26 # include "nsTerminator.h"
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"
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"
55 #include "nsVersionComparatorImpl.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"
70 #include "nsNSSComponent.h"
73 #include "mozilla/Services.h"
74 #include "mozilla/Omnijar.h"
75 #include "mozilla/ScriptPreloader.h"
76 #include "mozilla/Telemetry.h"
77 #include "mozilla/BackgroundHangMonitor.h"
79 #include "mozilla/PoisonIOInterposer.h"
80 #include "mozilla/LateWriteChecks.h"
82 #include "mozilla/scache/StartupCache.h"
84 #include "base/at_exit.h"
85 #include "base/command_line.h"
86 #include "base/message_loop.h"
88 #include "mozilla/ipc/BrowserProcessSubThread.h"
89 #include "mozilla/AvailableMemoryTracker.h"
90 #include "mozilla/ClearOnShutdown.h"
91 #include "mozilla/CountingAllocatorBase.h"
93 # include "mozilla/PHCManager.h"
95 #include "mozilla/UniquePtr.h"
96 #include "mozilla/ServoStyleConsts.h"
98 #include "mozilla/ipc/GeckoChildProcessHost.h"
102 #include "GeckoProfiler.h"
103 #include "ProfilerControl.h"
106 #include "js/Initialization.h"
107 #include "mozilla/StaticPrefs_javascript.h"
108 #include "XPCSelfHostedShmem.h"
110 #include "gfxPlatform.h"
112 using base::AtExitManager
;
113 using mozilla::ipc::BrowserProcessSubThread
;
115 // From toolkit/library/rust/lib.rs
116 extern "C" void GkRust_Init();
117 extern "C" void GkRust_Shutdown();
121 static AtExitManager
* sExitManager
;
122 static MessageLoop
* sMessageLoop
;
123 static bool sCommandLineWasInitialized
;
124 static BrowserProcessSubThread
* sIOThread
;
125 static mozilla::BackgroundHangMonitor
* sMainHangMonitor
;
127 } /* anonymous namespace */
129 // Registry Factory creation function defined in nsRegistry.cpp
130 // We hook into this function locally to create and register the registry
131 // Since noone outside xpcom needs to know about this and nsRegistry.cpp
132 // does not have a local include file, we are putting this definition
133 // here rather than in nsIRegistry.h
134 extern nsresult
NS_RegistryGetFactory(nsIFactory
** aFactory
);
135 extern nsresult
NS_CategoryManagerGetFactory(nsIFactory
**);
138 extern nsresult
CreateAnonTempFileRemover();
141 nsresult
nsThreadManagerGetSingleton(const nsIID
& aIID
, void** aInstancePtr
) {
142 NS_ASSERTION(aInstancePtr
, "null outptr");
143 return nsThreadManager::get().QueryInterface(aIID
, aInstancePtr
);
146 nsresult
nsLocalFileConstructor(const nsIID
& aIID
, void** aInstancePtr
) {
147 return nsLocalFile::nsLocalFileConstructor(aIID
, aInstancePtr
);
150 nsComponentManagerImpl
* nsComponentManagerImpl::gComponentManager
= nullptr;
151 bool gXPCOMShuttingDown
= false;
152 bool gXPCOMMainThreadEventsAreDoomed
= false;
153 char16_t
* gGREBinPath
= nullptr;
155 // gDebug will be freed during shutdown.
156 static nsIDebug2
* gDebug
= nullptr;
158 EXPORT_XPCOM_API(nsresult
)
159 NS_GetDebug(nsIDebug2
** aResult
) {
160 return nsDebugImpl::Create(NS_GET_IID(nsIDebug2
), (void**)aResult
);
163 class ICUReporter final
: public nsIMemoryReporter
,
164 public mozilla::CountingAllocatorBase
<ICUReporter
> {
168 static void* Alloc(const void*, size_t aSize
) {
170 void* result
= CountingMalloc(aSize
);
171 if (result
== nullptr) {
172 MOZ_CRASH("Ran out of memory while allocating for ICU");
176 return CountingMalloc(aSize
);
180 static void* Realloc(const void*, void* aPtr
, size_t aSize
) {
182 void* result
= CountingRealloc(aPtr
, aSize
);
183 if (result
== nullptr) {
184 MOZ_CRASH("Ran out of memory while reallocating for ICU");
188 return CountingRealloc(aPtr
, aSize
);
192 static void Free(const void*, void* aPtr
) { return CountingFree(aPtr
); }
196 CollectReports(nsIHandleReportCallback
* aHandleReport
, nsISupports
* aData
,
197 bool aAnonymize
) override
{
199 "explicit/icu", KIND_HEAP
, UNITS_BYTES
, MemoryAllocated(),
200 "Memory used by ICU, a Unicode and globalization support library.");
205 ~ICUReporter() = default;
208 NS_IMPL_ISUPPORTS(ICUReporter
, nsIMemoryReporter
)
210 class OggReporter final
: public nsIMemoryReporter
,
211 public mozilla::CountingAllocatorBase
<OggReporter
> {
217 CollectReports(nsIHandleReportCallback
* aHandleReport
, nsISupports
* aData
,
218 bool aAnonymize
) override
{
220 "explicit/media/libogg", KIND_HEAP
, UNITS_BYTES
, MemoryAllocated(),
221 "Memory allocated through libogg for Ogg, Theora, and related media "
227 ~OggReporter() = default;
230 NS_IMPL_ISUPPORTS(OggReporter
, nsIMemoryReporter
)
232 static bool sInitializedJS
= false;
234 static void InitializeJS() {
235 #if defined(ENABLE_WASM_SIMD) && \
236 (defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86))
237 // Update static engine preferences, such as AVX, before
238 // `JS_InitWithFailureDiagnostic` is called.
239 JS::SetAVXEnabled(mozilla::StaticPrefs::javascript_options_wasm_simd_avx());
242 const char* jsInitFailureReason
= JS_InitWithFailureDiagnostic();
243 if (jsInitFailureReason
) {
244 MOZ_CRASH_UNSAFE(jsInitFailureReason
);
248 // Note that on OSX, aBinDirectory will point to .app/Contents/Resources/browser
249 EXPORT_XPCOM_API(nsresult
)
250 NS_InitXPCOM(nsIServiceManager
** aResult
, nsIFile
* aBinDirectory
,
251 nsIDirectoryServiceProvider
* aAppFileLocationProvider
,
252 bool aInitJSContext
) {
253 static bool sInitialized
= false;
255 return NS_ERROR_FAILURE
;
264 // We don't have the arguments by hand here. If logging has already been
265 // initialized by a previous call to LogModule::Init with the arguments
266 // passed, passing (0, nullptr) is alright here.
267 mozilla::LogModule::Init(0, nullptr);
273 // We are not shutting down
274 gXPCOMShuttingDown
= false;
277 // Discover the current value of the umask, and save it where
278 // nsSystemInfo::Init can retrieve it when necessary. There is no way
279 // to read the umask without changing it, and the setting is process-
280 // global, so this must be done while we are still single-threaded; the
281 // nsSystemInfo object is typically created much later, when some piece
282 // of chrome JS wants it. The system call is specified as unable to fail.
283 nsSystemInfo::gUserUmask
= ::umask(0777);
284 ::umask(nsSystemInfo::gUserUmask
);
287 // Set up chromium libs
288 NS_ASSERTION(!sExitManager
&& !sMessageLoop
, "Bad logic!");
290 if (!AtExitManager::AlreadyRegistered()) {
291 sExitManager
= new AtExitManager();
294 MessageLoop
* messageLoop
= MessageLoop::current();
296 sMessageLoop
= new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT
);
297 sMessageLoop
->set_thread_name("Gecko");
298 // Set experimental values for main thread hangs:
299 // 128ms for transient hangs and 8192ms for permanent hangs
300 sMessageLoop
->set_hang_timeouts(128, 8192);
301 } else if (messageLoop
->type() == MessageLoop::TYPE_MOZILLA_CHILD
) {
302 messageLoop
->set_thread_name("Gecko_Child");
303 messageLoop
->set_hang_timeouts(128, 8192);
306 if (XRE_IsParentProcess() &&
307 !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO
)) {
308 mozilla::UniquePtr
<BrowserProcessSubThread
> ioThread
=
309 mozilla::MakeUnique
<BrowserProcessSubThread
>(
310 BrowserProcessSubThread::IO
);
312 base::Thread::Options options
;
313 options
.message_loop_type
= MessageLoop::TYPE_IO
;
314 if (NS_WARN_IF(!ioThread
->StartWithOptions(options
))) {
315 return NS_ERROR_FAILURE
;
318 sIOThread
= ioThread
.release();
321 // Establish the main thread here.
322 rv
= nsThreadManager::get().Init();
323 if (NS_WARN_IF(NS_FAILED(rv
))) {
328 // Set up the timer globals/timer thread
329 rv
= nsTimerImpl::Startup();
330 if (NS_WARN_IF(NS_FAILED(rv
))) {
335 // If the locale hasn't already been setup by our embedder,
336 // get us out of the "C" locale and into the system
337 if (strcmp(setlocale(LC_ALL
, nullptr), "C") == 0) {
338 setlocale(LC_ALL
, "");
342 nsDirectoryService::RealInit();
347 rv
= aBinDirectory
->IsDirectory(&value
);
349 if (NS_SUCCEEDED(rv
) && value
) {
350 nsDirectoryService::gService
->SetCurrentProcessDirectory(aBinDirectory
);
354 if (aAppFileLocationProvider
) {
355 rv
= nsDirectoryService::gService
->RegisterProvider(
356 aAppFileLocationProvider
);
362 nsCOMPtr
<nsIFile
> xpcomLib
;
363 nsDirectoryService::gService
->Get(NS_GRE_BIN_DIR
, NS_GET_IID(nsIFile
),
364 getter_AddRefs(xpcomLib
));
365 MOZ_ASSERT(xpcomLib
);
369 xpcomLib
->GetPath(path
);
370 gGREBinPath
= ToNewUnicode(path
);
372 xpcomLib
->AppendNative(nsDependentCString(XPCOM_DLL
));
373 nsDirectoryService::gService
->Set(NS_XPCOM_LIBRARY_FILE
, xpcomLib
);
375 if (!mozilla::Omnijar::IsInitialized()) {
376 // If you added a new process type that uses NS_InitXPCOM, and you're
377 // *sure* you don't want NS_InitMinimalXPCOM: in addition to everything
378 // else you'll probably have to do, please add it to the case in
379 // GeckoChildProcessHost.cpp which sets the greomni/appomni flags.
380 MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsContentProcess());
381 mozilla::Omnijar::Init();
384 if ((sCommandLineWasInitialized
= !CommandLine::IsInitialized())) {
386 CommandLine::Init(0, nullptr);
388 nsCOMPtr
<nsIFile
> binaryFile
;
389 nsDirectoryService::gService
->Get(NS_XPCOM_CURRENT_PROCESS_DIR
,
391 getter_AddRefs(binaryFile
));
392 if (NS_WARN_IF(!binaryFile
)) {
393 return NS_ERROR_FAILURE
;
396 rv
= binaryFile
->AppendNative("nonexistent-executable"_ns
);
397 if (NS_WARN_IF(NS_FAILED(rv
))) {
401 nsCString binaryPath
;
402 rv
= binaryFile
->GetNativePath(binaryPath
);
403 if (NS_WARN_IF(NS_FAILED(rv
))) {
407 static char const* const argv
= {strdup(binaryPath
.get())};
408 CommandLine::Init(1, &argv
);
412 NS_ASSERTION(nsComponentManagerImpl::gComponentManager
== nullptr,
413 "CompMgr not null at init");
415 // Create the Component/Service Manager
416 nsComponentManagerImpl::gComponentManager
= new nsComponentManagerImpl();
417 NS_ADDREF(nsComponentManagerImpl::gComponentManager
);
419 // Global cycle collector initialization.
420 if (!nsCycleCollector_init()) {
421 return NS_ERROR_UNEXPECTED
;
424 // And start it up for this thread too.
425 nsCycleCollector_startup();
427 // Register ICU memory functions. This really shouldn't be necessary: the
428 // JS engine should do this on its own inside JS_Init, and memory-reporting
429 // code should call a JSAPI function to observe ICU memory usage. But we
430 // can't define the alloc/free functions in the JS engine, because it can't
431 // depend on the XPCOM-based memory reporting goop. So for now, we have
433 mozilla::SetICUMemoryFunctions();
435 // Do the same for libogg.
436 ogg_set_mem_functions(
437 OggReporter::CountingMalloc
, OggReporter::CountingCalloc
,
438 OggReporter::CountingRealloc
, OggReporter::CountingFree
);
440 // Initialize the JS engine.
442 sInitializedJS
= true;
444 rv
= nsComponentManagerImpl::gComponentManager
->Init();
446 NS_RELEASE(nsComponentManagerImpl::gComponentManager
);
451 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
455 // This is the earliest possible moment we can start PHC while still being
456 // able to read prefs.
457 mozilla::InitPHCState();
460 // After autoreg, but before we actually instantiate any components,
461 // add any services listed in the "xpcom-directory-providers" category
462 // to the directory service.
463 nsDirectoryService::gService
->RegisterCategoryProviders();
465 // Init mozilla::SharedThreadPool (which needs the service manager).
466 mozilla::SharedThreadPool::InitStatics();
468 mozilla::scache::StartupCache::GetSingleton();
469 mozilla::AvailableMemoryTracker::Init();
471 // Notify observers of xpcom autoregistration start
472 NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY
, nullptr,
473 NS_XPCOM_STARTUP_OBSERVER_ID
);
475 CreateAnonTempFileRemover();
478 // The memory reporter manager is up and running -- register our reporters.
479 RegisterStrongMemoryReporter(new ICUReporter());
480 RegisterStrongMemoryReporter(new OggReporter());
481 xpc::SelfHostedShmem::GetSingleton().InitMemoryReporter();
483 mozilla::Telemetry::Init();
485 mozilla::BackgroundHangMonitor::Startup();
487 const MessageLoop
* const loop
= MessageLoop::current();
488 sMainHangMonitor
= new mozilla::BackgroundHangMonitor(
489 loop
->thread_name().c_str(), loop
->transient_hang_timeout(),
490 loop
->permanent_hang_timeout());
492 mozilla::dom::JSExecutionManager::Initialize();
494 if (aInitJSContext
) {
495 xpc::InitializeJSContext();
501 EXPORT_XPCOM_API(nsresult
)
502 NS_InitMinimalXPCOM() {
504 mozilla::TimeStamp::Startup();
508 // We don't have the arguments by hand here. If logging has already been
509 // initialized by a previous call to LogModule::Init with the arguments
510 // passed, passing (0, nullptr) is alright here.
511 mozilla::LogModule::Init(0, nullptr);
515 nsresult rv
= nsThreadManager::get().Init();
516 if (NS_WARN_IF(NS_FAILED(rv
))) {
520 // Set up the timer globals/timer thread.
521 rv
= nsTimerImpl::Startup();
522 if (NS_WARN_IF(NS_FAILED(rv
))) {
526 // Create the Component/Service Manager
527 nsComponentManagerImpl::gComponentManager
= new nsComponentManagerImpl();
528 NS_ADDREF(nsComponentManagerImpl::gComponentManager
);
530 rv
= nsComponentManagerImpl::gComponentManager
->Init();
532 NS_RELEASE(nsComponentManagerImpl::gComponentManager
);
536 // Global cycle collector initialization.
537 if (!nsCycleCollector_init()) {
538 return NS_ERROR_UNEXPECTED
;
541 mozilla::SharedThreadPool::InitStatics();
542 mozilla::Telemetry::Init();
543 mozilla::BackgroundHangMonitor::Startup();
549 // NS_ShutdownXPCOM()
551 // The shutdown sequence for xpcom would be
553 // - Notify "xpcom-shutdown" for modules to release primary (root) references
554 // - Shutdown XPCOM timers
555 // - Notify "xpcom-shutdown-threads" for thread joins
556 // - Shutdown the event queues
557 // - Release the Global Service Manager
558 // - Release all service instances held by the global service manager
559 // - Release the Global Service Manager itself
560 // - Release the Component Manager
561 // - Release all factories cached by the Component Manager
562 // - Notify module loaders to shut down
563 // - Unload Libraries
564 // - Release Contractid Cache held by Component Manager
565 // - Release dll abstraction held by Component Manager
566 // - Release the Registry held by Component Manager
567 // - Finally, release the component manager itself
569 EXPORT_XPCOM_API(nsresult
)
570 NS_ShutdownXPCOM(nsIServiceManager
* aServMgr
) {
571 return mozilla::ShutdownXPCOM(aServMgr
);
576 void SetICUMemoryFunctions() {
577 static bool sICUReporterInitialized
= false;
578 if (!sICUReporterInitialized
) {
579 if (!JS_SetICUMemoryFunctions(ICUReporter::Alloc
, ICUReporter::Realloc
,
580 ICUReporter::Free
)) {
581 MOZ_CRASH("JS_SetICUMemoryFunctions failed.");
583 sICUReporterInitialized
= true;
587 nsresult
ShutdownXPCOM(nsIServiceManager
* aServMgr
) {
588 // Make sure the hang monitor is enabled for shutdown.
589 BackgroundHangMonitor().NotifyActivity();
591 if (!NS_IsMainThread()) {
592 MOZ_CRASH("Shutdown on wrong thread");
595 // Notify observers of xpcom shutting down
597 // Block it so that the COMPtr will get deleted before we hit
598 // servicemanager shutdown
600 nsCOMPtr
<nsIThread
> thread
= do_GetCurrentThread();
601 if (NS_WARN_IF(!thread
)) {
602 return NS_ERROR_UNEXPECTED
;
605 mozilla::AppShutdown::AdvanceShutdownPhase(
606 mozilla::ShutdownPhase::XPCOMWillShutdown
);
608 // We want the service manager to be the subject of notifications
609 nsCOMPtr
<nsIServiceManager
> mgr
;
610 Unused
<< NS_GetServiceManager(getter_AddRefs(mgr
));
611 MOZ_DIAGNOSTIC_ASSERT(mgr
!= nullptr, "Service manager not present!");
612 mozilla::AppShutdown::AdvanceShutdownPhase(
613 mozilla::ShutdownPhase::XPCOMShutdown
, nullptr, do_QueryInterface(mgr
));
615 // This must happen after the shutdown of media and widgets, which
616 // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
617 gfxPlatform::ShutdownLayersIPC();
619 mozilla::AppShutdown::AdvanceShutdownPhase(
620 mozilla::ShutdownPhase::XPCOMShutdownThreads
);
622 // Prime an assertion at ThreadEventTarget::Dispatch to avoid late
623 // dispatches to non main-thread threads.
624 ThreadEventTarget::XPCOMShutdownThreadsNotificationFinished();
627 // Shutdown the timer thread and all timers that might still be alive
628 nsTimerImpl::Shutdown();
630 // Have an extra round of processing after the timers went away.
631 NS_ProcessPendingEvents(thread
);
633 // Shutdown all remaining threads. This method does not return until
634 // all threads created using the thread manager (with the exception of
635 // the main thread) have exited.
636 nsThreadManager::get().ShutdownNonMainThreads();
638 RefPtr
<nsObserverService
> observerService
;
639 CallGetService("@mozilla.org/observer-service;1",
640 (nsObserverService
**)getter_AddRefs(observerService
));
641 if (observerService
) {
642 observerService
->Shutdown();
645 // XPCOMShutdownFinal is the default phase for ClearOnShutdown.
646 // This AdvanceShutdownPhase will thus free most ClearOnShutdown()'ed
647 // smart pointers. Some destructors may fire extra main thread runnables
648 // that will be processed inside AdvanceShutdownPhase.
649 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::XPCOMShutdownFinal
);
651 // Shutdown the main thread, processing our very last round of events, and
652 // then mark that we've finished main thread event processing.
653 nsThreadManager::get().ShutdownMainThread();
654 gXPCOMMainThreadEventsAreDoomed
= true;
656 BackgroundHangMonitor().NotifyActivity();
658 mozilla::dom::JSExecutionManager::Shutdown();
661 // XPCOM is officially in shutdown mode NOW
662 // Set this only after the observers have been notified as this
663 // will cause servicemanager to become inaccessible.
664 mozilla::services::Shutdown();
666 // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
668 NS_IF_RELEASE(aServMgr
);
670 // Shutdown global servicemanager
671 if (nsComponentManagerImpl::gComponentManager
) {
672 nsComponentManagerImpl::gComponentManager
->FreeServices();
675 // Remove the remaining main thread representations
676 nsThreadManager::get().ReleaseMainThread();
677 AbstractThread::ShutdownMainThread();
679 // Release the directory service
680 nsDirectoryService::gService
= nullptr;
683 gGREBinPath
= nullptr;
685 // FIXME: This can cause harmless writes from sqlite committing
686 // log files. We have to ignore them before we can move
687 // the mozilla::PoisonWrite call before this point. See bug
688 // 834945 for the details.
689 mozJSModuleLoader::UnloadLoaders();
691 // Clear the profiler's JS context before cycle collection. The profiler will
692 // notify the JS engine that it can let go of any data it's holding on to for
693 // profiling purposes.
694 PROFILER_CLEAR_JS_CONTEXT();
696 bool shutdownCollect
;
697 #ifdef NS_FREE_PERMANENT_DATA
698 shutdownCollect
= true;
700 shutdownCollect
= !!PR_GetEnv("MOZ_CC_RUN_DURING_SHUTDOWN");
702 nsCycleCollector_shutdown(shutdownCollect
);
704 // There can be code trying to refer to global objects during the final cc
705 // shutdown. This is the phase for such global objects to correctly release.
706 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::CCPostLastCycleCollection
);
708 mozilla::scache::StartupCache::DeleteSingleton();
709 mozilla::ScriptPreloader::DeleteSingleton();
711 PROFILER_MARKER_UNTYPED("Shutdown xpcom", OTHER
);
713 // Shutdown xpcom. This will release all loaders and cause others holding
714 // a refcount to the component manager to release it.
715 if (nsComponentManagerImpl::gComponentManager
) {
716 DebugOnly
<nsresult
> rv
=
717 (nsComponentManagerImpl::gComponentManager
)->Shutdown();
718 NS_ASSERTION(NS_SUCCEEDED(rv
.value
), "Component Manager shutdown failed.");
720 NS_WARNING("Component Manager was never created ...");
723 if (sInitializedJS
) {
724 // Shut down the JS engine.
726 sInitializedJS
= false;
729 mozilla::ScriptPreloader::DeleteCacheDataSingleton();
731 // Release shared memory which might be borrowed by the JS engine.
732 xpc::SelfHostedShmem::Shutdown();
734 // After all threads have been joined and the component manager has been shut
735 // down, any remaining objects that could be holding NSS resources (should)
736 // have been released, so we can safely shut down NSS.
737 if (NSS_IsInitialized()) {
738 nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
739 if (NSS_Shutdown() != SECSuccess
) {
740 // If you're seeing this crash and/or warning, some NSS resources are
741 // still in use (see bugs 1417680 and 1230312). Set the environment
742 // variable 'MOZ_IGNORE_NSS_SHUTDOWN_LEAKS' to some value to ignore this.
743 // Also, if leak checking is enabled, report this as a fake leak instead
745 #if defined(DEBUG) && !defined(ANDROID)
746 if (!getenv("MOZ_IGNORE_NSS_SHUTDOWN_LEAKS") &&
747 !getenv("XPCOM_MEM_BLOAT_LOG") && !getenv("XPCOM_MEM_LEAK_LOG") &&
748 !getenv("XPCOM_MEM_REFCNT_LOG") && !getenv("XPCOM_MEM_COMPTR_LOG")) {
749 MOZ_CRASH("NSS_Shutdown failed");
751 # ifdef NS_BUILD_REFCNT_LOGGING
752 // Create a fake leak.
753 NS_LogCtor((void*)0x100, "NSSShutdownFailed", 100);
754 # endif // NS_BUILD_REFCNT_LOGGING
755 NS_WARNING("NSS_Shutdown failed");
758 NS_WARNING("NSS_Shutdown failed");
759 #endif // defined(DEBUG) && !defined(ANDROID)
763 // Finally, release the component manager last because it unloads the
765 if (nsComponentManagerImpl::gComponentManager
) {
767 NS_RELEASE2(nsComponentManagerImpl::gComponentManager
, cnt
);
768 NS_ASSERTION(cnt
== 0, "Component Manager being held past XPCOM shutdown.");
770 nsComponentManagerImpl::gComponentManager
= nullptr;
771 nsCategoryManager::Destroy();
775 #ifdef NS_FREE_PERMANENT_DATA
776 // By the time we're shutting down, there may still be async parse tasks going
777 // on in the Servo thread-pool. This is fairly uncommon, though not
778 // impossible. CSS parsing heavily uses the atom table, so obviously it's not
779 // fine to get rid of it.
781 // In leak-checking / ASAN / etc. builds, shut down the servo thread-pool,
782 // which will wait for all the work to be done. For other builds, we don't
783 // really want to wait on shutdown for possibly slow tasks. So just leak the
784 // atom table in those.
785 Servo_ShutdownThreadPool();
786 NS_ShutdownAtomTable();
789 NS_IF_RELEASE(gDebug
);
795 sMessageLoop
= nullptr;
797 mozilla::TaskController::Shutdown();
799 if (sCommandLineWasInitialized
) {
800 CommandLine::Terminate();
801 sCommandLineWasInitialized
= false;
805 sExitManager
= nullptr;
809 BackgroundHangMonitor::Shutdown();
811 delete sMainHangMonitor
;
812 sMainHangMonitor
= nullptr;
819 } // namespace mozilla