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/dom/SharedScriptCache.h"
34 #include "mozilla/SharedStyleSheetCache.h"
35 #include "mozilla/layers/ImageBridgeChild.h"
36 #include "mozilla/layers/CompositorBridgeParent.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"
57 #include "nsVersionComparatorImpl.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"
73 #include "nsNSSComponent.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"
96 # include "mozilla/PHCManager.h"
98 #include "mozilla/UniquePtr.h"
99 #include "mozilla/ServoStyleConsts.h"
101 #include "mozilla/ipc/GeckoChildProcessHost.h"
105 #include "GeckoProfiler.h"
106 #include "ProfilerControl.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();
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
**);
142 extern nsresult
CreateAnonTempFileRemover();
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
> {
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");
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");
188 static void Free(const void*, void* aPtr
) { return CountingFree(aPtr
); }
192 CollectReports(nsIHandleReportCallback
* aHandleReport
, nsISupports
* aData
,
193 bool aAnonymize
) override
{
195 "explicit/icu", KIND_HEAP
, UNITS_BYTES
, MemoryAllocated(),
196 "Memory used by ICU, a Unicode and globalization support library.");
201 ~ICUReporter() = default;
204 NS_IMPL_ISUPPORTS(ICUReporter
, nsIMemoryReporter
)
206 class OggReporter final
: public nsIMemoryReporter
,
207 public mozilla::CountingAllocatorBase
<OggReporter
> {
213 CollectReports(nsIHandleReportCallback
* aHandleReport
, nsISupports
* aData
,
214 bool aAnonymize
) override
{
216 "explicit/media/libogg", KIND_HEAP
, UNITS_BYTES
, MemoryAllocated(),
217 "Memory allocated through libogg for Ogg, and related media "
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());
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()) { \
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;
265 XPCOM_INIT_FATAL("!sInitialized", NS_ERROR_FAILURE
)
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);
283 // We are not shutting down
284 gXPCOMShuttingDown
= false;
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
);
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();
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
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
)
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
, "");
346 nsDirectoryService::RealInit();
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
);
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
);
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();
391 XPCOM_INIT_FATAL("Omnijar::Init()", NS_ERROR_OMNIJAR_CORRUPT
)
395 if ((sCommandLineWasInitialized
= !CommandLine::IsInitialized())) {
397 CommandLine::Init(0, nullptr);
399 nsCOMPtr
<nsIFile
> binaryFile
;
400 nsDirectoryService::gService
->Get(NS_XPCOM_CURRENT_PROCESS_DIR
,
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
);
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
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.
453 sInitializedJS
= true;
455 rv
= nsComponentManagerImpl::gComponentManager
->Init();
457 NS_RELEASE(nsComponentManagerImpl::gComponentManager
);
458 XPCOM_INIT_FATAL("gComponentManager->Init()", rv
)
462 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
466 // This is the earliest possible moment we can start PHC while still being
467 // able to read prefs.
468 mozilla::InitPHCState();
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
);
491 CreateAnonTempFileRemover();
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();
517 #undef XPCOM_INIT_FATAL
519 EXPORT_XPCOM_API(nsresult
)
520 NS_InitMinimalXPCOM() {
522 mozilla::TimeStamp::Startup();
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);
533 nsresult rv
= nsThreadManager::get().Init();
534 if (NS_WARN_IF(NS_FAILED(rv
))) {
538 // Set up the timer globals/timer thread.
539 rv
= nsTimerImpl::Startup();
540 if (NS_WARN_IF(NS_FAILED(rv
))) {
544 // Create the Component/Service Manager
545 nsComponentManagerImpl::gComponentManager
= new nsComponentManagerImpl();
546 NS_ADDREF(nsComponentManagerImpl::gComponentManager
);
548 rv
= nsComponentManagerImpl::gComponentManager
->Init();
550 NS_RELEASE(nsComponentManagerImpl::gComponentManager
);
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();
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
);
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
);
640 // Prime an assertion at ThreadEventTarget::Dispatch to avoid late
641 // dispatches to non main-thread threads.
642 ThreadEventTarget::XPCOMShutdownThreadsNotificationFinished();
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();
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
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;
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;
725 shutdownCollect
= !!PR_GetEnv("MOZ_CC_RUN_DURING_SHUTDOWN");
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.");
745 NS_WARNING("Component Manager was never created ...");
748 if (sInitializedJS
) {
749 // Shut down the JS engine.
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
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");
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");
786 NS_WARNING("NSS_Shutdown failed");
787 #endif // defined(DEBUG) && !defined(ANDROID)
791 // Finally, release the component manager last because it unloads the
793 if (nsComponentManagerImpl::gComponentManager
) {
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();
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();
813 NS_IF_RELEASE(gDebug
);
819 sMessageLoop
= nullptr;
821 mozilla::TaskController::Shutdown();
823 if (sCommandLineWasInitialized
) {
824 CommandLine::Terminate();
825 sCommandLineWasInitialized
= false;
829 sExitManager
= nullptr;
833 BackgroundHangMonitor::Shutdown();
835 delete sMainHangMonitor
;
836 sMainHangMonitor
= nullptr;
843 } // namespace mozilla