Source code

Revision control

Other Tools

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/. */
6
7
#include "XPCOMModule.h"
8
9
#include "base/basictypes.h"
10
11
#include "mozilla/Atomics.h"
12
#include "mozilla/Poison.h"
13
#include "mozilla/RemoteDecoderManagerChild.h"
14
#include "mozilla/SharedThreadPool.h"
15
#include "mozilla/XPCOM.h"
16
#include "mozJSComponentLoader.h"
17
#include "nsXULAppAPI.h"
18
19
#ifndef ANDROID
20
# include "nsTerminator.h"
21
#endif
22
23
#include "nsXPCOMPrivate.h"
24
#include "nsXPCOMCIDInternal.h"
25
26
#include "mozilla/layers/ImageBridgeChild.h"
27
#include "mozilla/layers/CompositorBridgeParent.h"
28
29
#include "prlink.h"
30
31
#include "nsCycleCollector.h"
32
#include "nsObserverService.h"
33
34
#include "nsDebugImpl.h"
35
#include "nsSystemInfo.h"
36
37
#include "nsINIParserImpl.h"
38
39
#include "nsComponentManager.h"
40
#include "nsCategoryManagerUtils.h"
41
#include "nsIServiceManager.h"
42
43
#include "nsThreadManager.h"
44
#include "nsThreadPool.h"
45
46
#include "nsTimerImpl.h"
47
#include "TimerThread.h"
48
49
#include "nsThread.h"
50
#include "nsVersionComparatorImpl.h"
51
52
#include "nsIFile.h"
53
#include "nsLocalFile.h"
54
#include "nsDirectoryService.h"
55
#include "nsDirectoryServiceDefs.h"
56
#include "nsCategoryManager.h"
57
#include "nsICategoryManager.h"
58
#include "nsMultiplexInputStream.h"
59
60
#include "nsAtomTable.h"
61
#include "nsISupportsImpl.h"
62
63
#include "nsSystemInfo.h"
64
#include "nsMemoryReporterManager.h"
65
#include "nsMessageLoop.h"
66
#include "nss.h"
67
#include "ssl.h"
68
69
#include <locale.h>
70
#include "mozilla/Services.h"
71
#include "mozilla/Omnijar.h"
72
#include "mozilla/ScriptPreloader.h"
73
#include "mozilla/SystemGroup.h"
74
#include "mozilla/Telemetry.h"
75
#include "mozilla/BackgroundHangMonitor.h"
76
77
#include "mozilla/PoisonIOInterposer.h"
78
#include "mozilla/LateWriteChecks.h"
79
80
#include "mozilla/scache/StartupCache.h"
81
82
#include "base/at_exit.h"
83
#include "base/command_line.h"
84
#include "base/message_loop.h"
85
86
#include "mozilla/ipc/BrowserProcessSubThread.h"
87
#include "mozilla/AvailableMemoryTracker.h"
88
#include "mozilla/ClearOnShutdown.h"
89
#include "mozilla/CountingAllocatorBase.h"
90
#include "mozilla/UniquePtr.h"
91
#include "mozilla/ServoStyleConsts.h"
92
93
#include "mozilla/ipc/GeckoChildProcessHost.h"
94
95
#include "ogg/ogg.h"
96
97
#include "GeckoProfiler.h"
98
99
#include "jsapi.h"
100
#include "js/Initialization.h"
101
102
#include "gfxPlatform.h"
103
104
using namespace mozilla;
105
using base::AtExitManager;
106
using mozilla::ipc::BrowserProcessSubThread;
107
108
// From toolkit/library/rust/lib.rs
109
extern "C" void GkRust_Init();
110
extern "C" void GkRust_Shutdown();
111
112
namespace {
113
114
static AtExitManager* sExitManager;
115
static MessageLoop* sMessageLoop;
116
static bool sCommandLineWasInitialized;
117
static BrowserProcessSubThread* sIOThread;
118
static BackgroundHangMonitor* sMainHangMonitor;
119
120
} /* anonymous namespace */
121
122
// Registry Factory creation function defined in nsRegistry.cpp
123
// We hook into this function locally to create and register the registry
124
// Since noone outside xpcom needs to know about this and nsRegistry.cpp
125
// does not have a local include file, we are putting this definition
126
// here rather than in nsIRegistry.h
127
extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
128
extern nsresult NS_CategoryManagerGetFactory(nsIFactory**);
129
130
#ifdef XP_WIN
131
extern nsresult CreateAnonTempFileRemover();
132
#endif
133
134
nsresult nsThreadManagerGetSingleton(nsISupports* aOuter, const nsIID& aIID,
135
void** aInstancePtr) {
136
NS_ASSERTION(aInstancePtr, "null outptr");
137
if (NS_WARN_IF(aOuter)) {
138
return NS_ERROR_NO_AGGREGATION;
139
}
140
141
return nsThreadManager::get().QueryInterface(aIID, aInstancePtr);
142
}
143
144
nsresult nsLocalFileConstructor(nsISupports* aOuter, const nsIID& aIID,
145
void** aInstancePtr) {
146
return nsLocalFile::nsLocalFileConstructor(aOuter, aIID, aInstancePtr);
147
}
148
149
nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = nullptr;
150
bool gXPCOMShuttingDown = false;
151
bool gXPCOMThreadsShutDown = false;
152
char16_t* gGREBinPath = nullptr;
153
154
static NS_DEFINE_CID(kINIParserFactoryCID, NS_INIPARSERFACTORY_CID);
155
156
static already_AddRefed<nsIFactory> CreateINIParserFactory(
157
const mozilla::Module& aModule, const mozilla::Module::CIDEntry& aEntry) {
158
nsCOMPtr<nsIFactory> f = new nsINIParserFactory();
159
return f.forget();
160
}
161
162
const mozilla::Module::CIDEntry kXPCOMCIDEntries[] = {
163
{&kINIParserFactoryCID, false, CreateINIParserFactory}, {nullptr}};
164
165
const mozilla::Module::ContractIDEntry kXPCOMContracts[] = {
166
{NS_INIPARSERFACTORY_CONTRACTID, &kINIParserFactoryCID}, {nullptr}};
167
168
const mozilla::Module kXPCOMModule = {
169
mozilla::Module::kVersion,
170
kXPCOMCIDEntries,
171
kXPCOMContracts,
172
nullptr,
173
nullptr,
174
nullptr,
175
nullptr,
176
Module::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS};
177
178
// gDebug will be freed during shutdown.
179
static nsIDebug2* gDebug = nullptr;
180
181
EXPORT_XPCOM_API(nsresult)
182
NS_GetDebug(nsIDebug2** aResult) {
183
return nsDebugImpl::Create(nullptr, NS_GET_IID(nsIDebug2), (void**)aResult);
184
}
185
186
class ICUReporter final : public nsIMemoryReporter,
187
public CountingAllocatorBase<ICUReporter> {
188
public:
189
NS_DECL_ISUPPORTS
190
191
static void* Alloc(const void*, size_t aSize) {
192
return CountingMalloc(aSize);
193
}
194
195
static void* Realloc(const void*, void* aPtr, size_t aSize) {
196
return CountingRealloc(aPtr, aSize);
197
}
198
199
static void Free(const void*, void* aPtr) { return CountingFree(aPtr); }
200
201
private:
202
NS_IMETHOD
203
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
204
bool aAnonymize) override {
205
MOZ_COLLECT_REPORT(
206
"explicit/icu", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
207
"Memory used by ICU, a Unicode and globalization support library.");
208
209
return NS_OK;
210
}
211
212
~ICUReporter() {}
213
};
214
215
NS_IMPL_ISUPPORTS(ICUReporter, nsIMemoryReporter)
216
217
/* static */ template <>
218
CountingAllocatorBase<ICUReporter>::AmountType
219
CountingAllocatorBase<ICUReporter>::sAmount(0);
220
221
class OggReporter final : public nsIMemoryReporter,
222
public CountingAllocatorBase<OggReporter> {
223
public:
224
NS_DECL_ISUPPORTS
225
226
private:
227
NS_IMETHOD
228
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
229
bool aAnonymize) override {
230
MOZ_COLLECT_REPORT(
231
"explicit/media/libogg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
232
"Memory allocated through libogg for Ogg, Theora, and related media "
233
"files.");
234
235
return NS_OK;
236
}
237
238
~OggReporter() {}
239
};
240
241
NS_IMPL_ISUPPORTS(OggReporter, nsIMemoryReporter)
242
243
/* static */ template <>
244
CountingAllocatorBase<OggReporter>::AmountType
245
CountingAllocatorBase<OggReporter>::sAmount(0);
246
247
static bool sInitializedJS = false;
248
249
// Note that on OSX, aBinDirectory will point to .app/Contents/Resources/browser
250
EXPORT_XPCOM_API(nsresult)
251
NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
252
nsIDirectoryServiceProvider* aAppFileLocationProvider) {
253
static bool sInitialized = false;
254
if (sInitialized) {
255
return NS_ERROR_FAILURE;
256
}
257
258
sInitialized = true;
259
260
mozPoisonValueInit();
261
262
NS_LogInit();
263
264
NS_InitAtomTable();
265
266
// We don't have the arguments by hand here. If logging has already been
267
// initialized by a previous call to LogModule::Init with the arguments
268
// passed, passing (0, nullptr) is alright here.
269
mozilla::LogModule::Init(0, nullptr);
270
271
GkRust_Init();
272
273
nsresult rv = NS_OK;
274
275
// We are not shutting down
276
gXPCOMShuttingDown = false;
277
278
#ifdef XP_UNIX
279
// Discover the current value of the umask, and save it where
280
// nsSystemInfo::Init can retrieve it when necessary. There is no way
281
// to read the umask without changing it, and the setting is process-
282
// global, so this must be done while we are still single-threaded; the
283
// nsSystemInfo object is typically created much later, when some piece
284
// of chrome JS wants it. The system call is specified as unable to fail.
285
nsSystemInfo::gUserUmask = ::umask(0777);
286
::umask(nsSystemInfo::gUserUmask);
287
#endif
288
289
// Set up chromium libs
290
NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
291
292
if (!AtExitManager::AlreadyRegistered()) {
293
sExitManager = new AtExitManager();
294
}
295
296
MessageLoop* messageLoop = MessageLoop::current();
297
if (!messageLoop) {
298
sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT);
299
sMessageLoop->set_thread_name("Gecko");
300
// Set experimental values for main thread hangs:
301
// 128ms for transient hangs and 8192ms for permanent hangs
302
sMessageLoop->set_hang_timeouts(128, 8192);
303
} else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) {
304
messageLoop->set_thread_name("Gecko_Child");
305
messageLoop->set_hang_timeouts(128, 8192);
306
}
307
308
if (XRE_IsParentProcess() &&
309
!BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) {
310
UniquePtr<BrowserProcessSubThread> ioThread =
311
MakeUnique<BrowserProcessSubThread>(BrowserProcessSubThread::IO);
312
313
base::Thread::Options options;
314
options.message_loop_type = MessageLoop::TYPE_IO;
315
if (NS_WARN_IF(!ioThread->StartWithOptions(options))) {
316
return NS_ERROR_FAILURE;
317
}
318
319
sIOThread = ioThread.release();
320
}
321
322
// Establish the main thread here.
323
rv = nsThreadManager::get().Init();
324
if (NS_WARN_IF(NS_FAILED(rv))) {
325
return rv;
326
}
327
328
// Init the SystemGroup for dispatching main thread runnables.
329
SystemGroup::InitStatic();
330
331
// Set up the timer globals/timer thread
332
rv = nsTimerImpl::Startup();
333
if (NS_WARN_IF(NS_FAILED(rv))) {
334
return rv;
335
}
336
337
#ifndef ANDROID
338
// If the locale hasn't already been setup by our embedder,
339
// get us out of the "C" locale and into the system
340
if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) {
341
setlocale(LC_ALL, "");
342
}
343
#endif
344
345
nsDirectoryService::RealInit();
346
347
bool value;
348
349
if (aBinDirectory) {
350
rv = aBinDirectory->IsDirectory(&value);
351
352
if (NS_SUCCEEDED(rv) && value) {
353
nsDirectoryService::gService->SetCurrentProcessDirectory(aBinDirectory);
354
}
355
}
356
357
if (aAppFileLocationProvider) {
358
rv = nsDirectoryService::gService->RegisterProvider(
359
aAppFileLocationProvider);
360
if (NS_FAILED(rv)) {
361
return rv;
362
}
363
}
364
365
nsCOMPtr<nsIFile> xpcomLib;
366
nsDirectoryService::gService->Get(NS_GRE_BIN_DIR, NS_GET_IID(nsIFile),
367
getter_AddRefs(xpcomLib));
368
MOZ_ASSERT(xpcomLib);
369
370
// set gGREBinPath
371
nsAutoString path;
372
xpcomLib->GetPath(path);
373
gGREBinPath = ToNewUnicode(path);
374
375
xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
376
nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
377
378
if (!mozilla::Omnijar::IsInitialized()) {
379
mozilla::Omnijar::Init();
380
}
381
382
if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
383
#ifdef OS_WIN
384
CommandLine::Init(0, nullptr);
385
#else
386
nsCOMPtr<nsIFile> binaryFile;
387
nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
388
NS_GET_IID(nsIFile),
389
getter_AddRefs(binaryFile));
390
if (NS_WARN_IF(!binaryFile)) {
391
return NS_ERROR_FAILURE;
392
}
393
394
rv = binaryFile->AppendNative(NS_LITERAL_CSTRING("nonexistent-executable"));
395
if (NS_WARN_IF(NS_FAILED(rv))) {
396
return rv;
397
}
398
399
nsCString binaryPath;
400
rv = binaryFile->GetNativePath(binaryPath);
401
if (NS_WARN_IF(NS_FAILED(rv))) {
402
return rv;
403
}
404
405
static char const* const argv = {strdup(binaryPath.get())};
406
CommandLine::Init(1, &argv);
407
#endif
408
}
409
410
NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr,
411
"CompMgr not null at init");
412
413
// Create the Component/Service Manager
414
nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
415
NS_ADDREF(nsComponentManagerImpl::gComponentManager);
416
417
// Global cycle collector initialization.
418
if (!nsCycleCollector_init()) {
419
return NS_ERROR_UNEXPECTED;
420
}
421
422
// And start it up for this thread too.
423
nsCycleCollector_startup();
424
425
// Register ICU memory functions. This really shouldn't be necessary: the
426
// JS engine should do this on its own inside JS_Init, and memory-reporting
427
// code should call a JSAPI function to observe ICU memory usage. But we
428
// can't define the alloc/free functions in the JS engine, because it can't
429
// depend on the XPCOM-based memory reporting goop. So for now, we have
430
// this oddness.
431
mozilla::SetICUMemoryFunctions();
432
433
// Do the same for libogg.
434
ogg_set_mem_functions(
435
OggReporter::CountingMalloc, OggReporter::CountingCalloc,
436
OggReporter::CountingRealloc, OggReporter::CountingFree);
437
438
// Initialize the JS engine.
439
const char* jsInitFailureReason = JS_InitWithFailureDiagnostic();
440
if (jsInitFailureReason) {
441
MOZ_CRASH_UNSAFE(jsInitFailureReason);
442
}
443
sInitializedJS = true;
444
445
rv = nsComponentManagerImpl::gComponentManager->Init();
446
if (NS_FAILED(rv)) {
447
NS_RELEASE(nsComponentManagerImpl::gComponentManager);
448
return rv;
449
}
450
451
if (aResult) {
452
NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
453
}
454
455
// After autoreg, but before we actually instantiate any components,
456
// add any services listed in the "xpcom-directory-providers" category
457
// to the directory service.
458
nsDirectoryService::gService->RegisterCategoryProviders();
459
460
// Init SharedThreadPool (which needs the service manager).
461
SharedThreadPool::InitStatics();
462
463
mozilla::ScriptPreloader::GetSingleton();
464
mozilla::scache::StartupCache::GetSingleton();
465
mozilla::AvailableMemoryTracker::Init();
466
467
// Notify observers of xpcom autoregistration start
468
NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nullptr,
469
NS_XPCOM_STARTUP_OBSERVER_ID);
470
#ifdef XP_WIN
471
CreateAnonTempFileRemover();
472
#endif
473
474
// The memory reporter manager is up and running -- register our reporters.
475
RegisterStrongMemoryReporter(new ICUReporter());
476
RegisterStrongMemoryReporter(new OggReporter());
477
478
mozilla::Telemetry::Init();
479
480
mozilla::BackgroundHangMonitor::Startup();
481
482
const MessageLoop* const loop = MessageLoop::current();
483
sMainHangMonitor = new mozilla::BackgroundHangMonitor(
484
loop->thread_name().c_str(), loop->transient_hang_timeout(),
485
loop->permanent_hang_timeout());
486
487
return NS_OK;
488
}
489
490
EXPORT_XPCOM_API(nsresult)
491
NS_InitMinimalXPCOM() {
492
mozPoisonValueInit();
493
NS_SetMainThread();
494
mozilla::TimeStamp::Startup();
495
NS_LogInit();
496
NS_InitAtomTable();
497
498
// We don't have the arguments by hand here. If logging has already been
499
// initialized by a previous call to LogModule::Init with the arguments
500
// passed, passing (0, nullptr) is alright here.
501
mozilla::LogModule::Init(0, nullptr);
502
503
GkRust_Init();
504
505
nsresult rv = nsThreadManager::get().Init();
506
if (NS_WARN_IF(NS_FAILED(rv))) {
507
return rv;
508
}
509
510
// Init the SystemGroup for dispatching main thread runnables.
511
SystemGroup::InitStatic();
512
513
// Set up the timer globals/timer thread.
514
rv = nsTimerImpl::Startup();
515
if (NS_WARN_IF(NS_FAILED(rv))) {
516
return rv;
517
}
518
519
// Create the Component/Service Manager
520
nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
521
NS_ADDREF(nsComponentManagerImpl::gComponentManager);
522
523
rv = nsComponentManagerImpl::gComponentManager->Init();
524
if (NS_FAILED(rv)) {
525
NS_RELEASE(nsComponentManagerImpl::gComponentManager);
526
return rv;
527
}
528
529
// Global cycle collector initialization.
530
if (!nsCycleCollector_init()) {
531
return NS_ERROR_UNEXPECTED;
532
}
533
534
SharedThreadPool::InitStatics();
535
mozilla::Telemetry::Init();
536
mozilla::BackgroundHangMonitor::Startup();
537
538
return NS_OK;
539
}
540
541
//
542
// NS_ShutdownXPCOM()
543
//
544
// The shutdown sequence for xpcom would be
545
//
546
// - Notify "xpcom-shutdown" for modules to release primary (root) references
547
// - Shutdown XPCOM timers
548
// - Notify "xpcom-shutdown-threads" for thread joins
549
// - Shutdown the event queues
550
// - Release the Global Service Manager
551
// - Release all service instances held by the global service manager
552
// - Release the Global Service Manager itself
553
// - Release the Component Manager
554
// - Release all factories cached by the Component Manager
555
// - Notify module loaders to shut down
556
// - Unload Libraries
557
// - Release Contractid Cache held by Component Manager
558
// - Release dll abstraction held by Component Manager
559
// - Release the Registry held by Component Manager
560
// - Finally, release the component manager itself
561
//
562
EXPORT_XPCOM_API(nsresult)
563
NS_ShutdownXPCOM(nsIServiceManager* aServMgr) {
564
return mozilla::ShutdownXPCOM(aServMgr);
565
}
566
567
namespace mozilla {
568
569
void SetICUMemoryFunctions() {
570
static bool sICUReporterInitialized = false;
571
if (!sICUReporterInitialized) {
572
if (!JS_SetICUMemoryFunctions(ICUReporter::Alloc, ICUReporter::Realloc,
573
ICUReporter::Free)) {
574
MOZ_CRASH("JS_SetICUMemoryFunctions failed.");
575
}
576
sICUReporterInitialized = true;
577
}
578
}
579
580
nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) {
581
// Make sure the hang monitor is enabled for shutdown.
582
BackgroundHangMonitor().NotifyActivity();
583
584
if (!NS_IsMainThread()) {
585
MOZ_CRASH("Shutdown on wrong thread");
586
}
587
588
nsresult rv;
589
590
// Notify observers of xpcom shutting down
591
{
592
// Block it so that the COMPtr will get deleted before we hit
593
// servicemanager shutdown
594
595
nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
596
if (NS_WARN_IF(!thread)) {
597
return NS_ERROR_UNEXPECTED;
598
}
599
600
RefPtr<nsObserverService> observerService;
601
CallGetService("@mozilla.org/observer-service;1",
602
(nsObserverService**)getter_AddRefs(observerService));
603
604
if (observerService) {
605
mozilla::KillClearOnShutdown(ShutdownPhase::WillShutdown);
606
observerService->NotifyObservers(
607
nullptr, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, nullptr);
608
609
nsCOMPtr<nsIServiceManager> mgr;
610
rv = NS_GetServiceManager(getter_AddRefs(mgr));
611
if (NS_SUCCEEDED(rv)) {
612
mozilla::KillClearOnShutdown(ShutdownPhase::Shutdown);
613
observerService->NotifyObservers(mgr, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
614
nullptr);
615
}
616
617
#ifndef ANDROID
618
mozilla::XPCOMShutdownNotified();
619
#endif
620
}
621
622
// This must happen after the shutdown of media and widgets, which
623
// are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
624
NS_ProcessPendingEvents(thread);
625
gfxPlatform::ShutdownLayersIPC();
626
mozilla::RemoteDecoderManagerChild::Shutdown();
627
628
mozilla::scache::StartupCache::DeleteSingleton();
629
if (observerService) {
630
mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownThreads);
631
observerService->NotifyObservers(
632
nullptr, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, nullptr);
633
}
634
635
gXPCOMThreadsShutDown = true;
636
NS_ProcessPendingEvents(thread);
637
638
// Shutdown the timer thread and all timers that might still be alive before
639
// shutting down the component manager
640
nsTimerImpl::Shutdown();
641
642
NS_ProcessPendingEvents(thread);
643
644
// Shutdown all remaining threads. This method does not return until
645
// all threads created using the thread manager (with the exception of
646
// the main thread) have exited.
647
nsThreadManager::get().Shutdown();
648
649
NS_ProcessPendingEvents(thread);
650
651
BackgroundHangMonitor().NotifyActivity();
652
653
// Late-write checks needs to find the profile directory, so it has to
654
// be initialized before mozilla::services::Shutdown or (because of
655
// xpcshell tests replacing the service) modules being unloaded.
656
mozilla::InitLateWriteChecks();
657
658
if (observerService) {
659
mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownLoaders);
660
observerService->Shutdown();
661
}
662
}
663
664
// Free ClearOnShutdown()'ed smart pointers. This needs to happen *after*
665
// we've finished notifying observers of XPCOM shutdown, because shutdown
666
// observers themselves might call ClearOnShutdown().
667
mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownFinal);
668
669
// XPCOM is officially in shutdown mode NOW
670
// Set this only after the observers have been notified as this
671
// will cause servicemanager to become inaccessible.
672
mozilla::services::Shutdown();
673
674
// We may have AddRef'd for the caller of NS_InitXPCOM, so release it
675
// here again:
676
NS_IF_RELEASE(aServMgr);
677
678
// Shutdown global servicemanager
679
if (nsComponentManagerImpl::gComponentManager) {
680
nsComponentManagerImpl::gComponentManager->FreeServices();
681
}
682
683
// Release the directory service
684
nsDirectoryService::gService = nullptr;
685
686
free(gGREBinPath);
687
gGREBinPath = nullptr;
688
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
mozJSComponentLoader::Unload();
694
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();
699
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);
707
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
mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownPostLastCycleCollection);
711
712
PROFILER_ADD_MARKER("Shutdown xpcom", OTHER);
713
// If we are doing any shutdown checks, poison writes.
714
if (gShutdownChecks != SCM_NOTHING) {
715
#ifdef XP_MACOSX
716
mozilla::OnlyReportDirtyWrites();
717
#endif /* XP_MACOSX */
718
mozilla::BeginLateWriteChecks();
719
}
720
721
// Shutdown xpcom. This will release all loaders and cause others holding
722
// a refcount to the component manager to release it.
723
if (nsComponentManagerImpl::gComponentManager) {
724
rv = (nsComponentManagerImpl::gComponentManager)->Shutdown();
725
NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");
726
} else {
727
NS_WARNING("Component Manager was never created ...");
728
}
729
730
if (sInitializedJS) {
731
// Shut down the JS engine.
732
JS_ShutDown();
733
sInitializedJS = false;
734
}
735
736
// After all threads have been joined and the component manager has been shut
737
// down, any remaining objects that could be holding NSS resources (should)
738
// have been released, so we can safely shut down NSS.
739
if (NSS_IsInitialized()) {
740
SSL_ClearSessionCache();
741
if (NSS_Shutdown() != SECSuccess) {
742
// If you're seeing this crash and/or warning, some NSS resources are
743
// still in use (see bugs 1417680 and 1230312). Set the environment
744
// variable 'MOZ_IGNORE_NSS_SHUTDOWN_LEAKS' to some value to ignore this.
745
#if defined(DEBUG) && !defined(ANDROID)
746
if (!getenv("MOZ_IGNORE_NSS_SHUTDOWN_LEAKS")) {
747
MOZ_CRASH("NSS_Shutdown failed");
748
} else {
749
NS_WARNING("NSS_Shutdown failed");
750
}
751
#else
752
NS_WARNING("NSS_Shutdown failed");
753
#endif
754
}
755
}
756
757
// Finally, release the component manager last because it unloads the
758
// libraries:
759
if (nsComponentManagerImpl::gComponentManager) {
760
nsrefcnt cnt;
761
NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
762
NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown.");
763
}
764
nsComponentManagerImpl::gComponentManager = nullptr;
765
nsCategoryManager::Destroy();
766
767
// Shut down SystemGroup for main thread dispatching.
768
SystemGroup::Shutdown();
769
770
GkRust_Shutdown();
771
772
#ifdef NS_FREE_PERMANENT_DATA
773
// By the time we're shutting down, there may still be async parse tasks going
774
// on in the Servo thread-pool. This is fairly uncommon, though not
775
// impossible. CSS parsing heavily uses the atom table, so obviously it's not
776
// fine to get rid of it.
777
//
778
// In leak-checking / ASAN / etc. builds, shut down the servo thread-pool,
779
// which will wait for all the work to be done. For other builds, we don't
780
// really want to wait on shutdown for possibly slow tasks. So just leak the
781
// atom table in those.
782
Servo_ShutdownThreadPool();
783
NS_ShutdownAtomTable();
784
#endif
785
786
NS_IF_RELEASE(gDebug);
787
788
delete sIOThread;
789
sIOThread = nullptr;
790
791
delete sMessageLoop;
792
sMessageLoop = nullptr;
793
794
if (sCommandLineWasInitialized) {
795
CommandLine::Terminate();
796
sCommandLineWasInitialized = false;
797
}
798
799
delete sExitManager;
800
sExitManager = nullptr;
801
802
Omnijar::CleanUp();
803
804
BackgroundHangMonitor::Shutdown();
805
806
delete sMainHangMonitor;
807
sMainHangMonitor = nullptr;
808
809
NS_LogTerm();
810
811
return NS_OK;
812
}
813
814
} // namespace mozilla