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
92
#include "mozilla/ipc/GeckoChildProcessHost.h"
93
94
#include "ogg/ogg.h"
95
96
#include "GeckoProfiler.h"
97
98
#include "jsapi.h"
99
#include "js/Initialization.h"
100
101
#include "gfxPlatform.h"
102
103
using namespace mozilla;
104
using base::AtExitManager;
105
using mozilla::ipc::BrowserProcessSubThread;
106
107
// From toolkit/library/rust/lib.rs
108
extern "C" void GkRust_Init();
109
extern "C" void GkRust_Shutdown();
110
111
namespace {
112
113
static AtExitManager* sExitManager;
114
static MessageLoop* sMessageLoop;
115
static bool sCommandLineWasInitialized;
116
static BrowserProcessSubThread* sIOThread;
117
static BackgroundHangMonitor* sMainHangMonitor;
118
119
} /* anonymous namespace */
120
121
// Registry Factory creation function defined in nsRegistry.cpp
122
// We hook into this function locally to create and register the registry
123
// Since noone outside xpcom needs to know about this and nsRegistry.cpp
124
// does not have a local include file, we are putting this definition
125
// here rather than in nsIRegistry.h
126
extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
127
extern nsresult NS_CategoryManagerGetFactory(nsIFactory**);
128
129
#ifdef XP_WIN
130
extern nsresult CreateAnonTempFileRemover();
131
#endif
132
133
nsresult nsThreadManagerGetSingleton(nsISupports* aOuter, const nsIID& aIID,
134
void** aInstancePtr) {
135
NS_ASSERTION(aInstancePtr, "null outptr");
136
if (NS_WARN_IF(aOuter)) {
137
return NS_ERROR_NO_AGGREGATION;
138
}
139
140
return nsThreadManager::get().QueryInterface(aIID, aInstancePtr);
141
}
142
143
nsresult nsLocalFileConstructor(nsISupports* aOuter, const nsIID& aIID,
144
void** aInstancePtr) {
145
return nsLocalFile::nsLocalFileConstructor(aOuter, aIID, aInstancePtr);
146
}
147
148
nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = nullptr;
149
bool gXPCOMShuttingDown = false;
150
bool gXPCOMThreadsShutDown = false;
151
char16_t* gGREBinPath = nullptr;
152
153
static NS_DEFINE_CID(kINIParserFactoryCID, NS_INIPARSERFACTORY_CID);
154
155
static already_AddRefed<nsIFactory> CreateINIParserFactory(
156
const mozilla::Module& aModule, const mozilla::Module::CIDEntry& aEntry) {
157
nsCOMPtr<nsIFactory> f = new nsINIParserFactory();
158
return f.forget();
159
}
160
161
const mozilla::Module::CIDEntry kXPCOMCIDEntries[] = {
162
{&kINIParserFactoryCID, false, CreateINIParserFactory}, {nullptr}};
163
164
const mozilla::Module::ContractIDEntry kXPCOMContracts[] = {
165
{NS_INIPARSERFACTORY_CONTRACTID, &kINIParserFactoryCID}, {nullptr}};
166
167
const mozilla::Module kXPCOMModule = {
168
mozilla::Module::kVersion,
169
kXPCOMCIDEntries,
170
kXPCOMContracts,
171
nullptr,
172
nullptr,
173
nullptr,
174
nullptr,
175
Module::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS};
176
177
// gDebug will be freed during shutdown.
178
static nsIDebug2* gDebug = nullptr;
179
180
EXPORT_XPCOM_API(nsresult)
181
NS_GetDebug(nsIDebug2** aResult) {
182
return nsDebugImpl::Create(nullptr, NS_GET_IID(nsIDebug2), (void**)aResult);
183
}
184
185
class ICUReporter final : public nsIMemoryReporter,
186
public CountingAllocatorBase<ICUReporter> {
187
public:
188
NS_DECL_ISUPPORTS
189
190
static void* Alloc(const void*, size_t aSize) {
191
return CountingMalloc(aSize);
192
}
193
194
static void* Realloc(const void*, void* aPtr, size_t aSize) {
195
return CountingRealloc(aPtr, aSize);
196
}
197
198
static void Free(const void*, void* aPtr) { return CountingFree(aPtr); }
199
200
private:
201
NS_IMETHOD
202
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
203
bool aAnonymize) override {
204
MOZ_COLLECT_REPORT(
205
"explicit/icu", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
206
"Memory used by ICU, a Unicode and globalization support library.");
207
208
return NS_OK;
209
}
210
211
~ICUReporter() {}
212
};
213
214
NS_IMPL_ISUPPORTS(ICUReporter, nsIMemoryReporter)
215
216
/* static */ template <>
217
CountingAllocatorBase<ICUReporter>::AmountType
218
CountingAllocatorBase<ICUReporter>::sAmount(0);
219
220
class OggReporter final : public nsIMemoryReporter,
221
public CountingAllocatorBase<OggReporter> {
222
public:
223
NS_DECL_ISUPPORTS
224
225
private:
226
NS_IMETHOD
227
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
228
bool aAnonymize) override {
229
MOZ_COLLECT_REPORT(
230
"explicit/media/libogg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
231
"Memory allocated through libogg for Ogg, Theora, and related media "
232
"files.");
233
234
return NS_OK;
235
}
236
237
~OggReporter() {}
238
};
239
240
NS_IMPL_ISUPPORTS(OggReporter, nsIMemoryReporter)
241
242
/* static */ template <>
243
CountingAllocatorBase<OggReporter>::AmountType
244
CountingAllocatorBase<OggReporter>::sAmount(0);
245
246
static bool sInitializedJS = false;
247
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
static bool sInitialized = false;
253
if (sInitialized) {
254
return NS_ERROR_FAILURE;
255
}
256
257
sInitialized = true;
258
259
mozPoisonValueInit();
260
261
NS_LogInit();
262
263
NS_InitAtomTable();
264
265
// We don't have the arguments by hand here. If logging has already been
266
// initialized by a previous call to LogModule::Init with the arguments
267
// passed, passing (0, nullptr) is alright here.
268
mozilla::LogModule::Init(0, nullptr);
269
270
GkRust_Init();
271
272
nsresult rv = NS_OK;
273
274
// We are not shutting down
275
gXPCOMShuttingDown = false;
276
277
#ifdef XP_UNIX
278
// Discover the current value of the umask, and save it where
279
// nsSystemInfo::Init can retrieve it when necessary. There is no way
280
// to read the umask without changing it, and the setting is process-
281
// global, so this must be done while we are still single-threaded; the
282
// nsSystemInfo object is typically created much later, when some piece
283
// of chrome JS wants it. The system call is specified as unable to fail.
284
nsSystemInfo::gUserUmask = ::umask(0777);
285
::umask(nsSystemInfo::gUserUmask);
286
#endif
287
288
// Set up chromium libs
289
NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
290
291
if (!AtExitManager::AlreadyRegistered()) {
292
sExitManager = new AtExitManager();
293
}
294
295
MessageLoop* messageLoop = MessageLoop::current();
296
if (!messageLoop) {
297
sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT);
298
sMessageLoop->set_thread_name("Gecko");
299
// Set experimental values for main thread hangs:
300
// 128ms for transient hangs and 8192ms for permanent hangs
301
sMessageLoop->set_hang_timeouts(128, 8192);
302
} else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) {
303
messageLoop->set_thread_name("Gecko_Child");
304
messageLoop->set_hang_timeouts(128, 8192);
305
}
306
307
if (XRE_IsParentProcess() &&
308
!BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) {
309
UniquePtr<BrowserProcessSubThread> ioThread =
310
MakeUnique<BrowserProcessSubThread>(BrowserProcessSubThread::IO);
311
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;
316
}
317
318
sIOThread = ioThread.release();
319
}
320
321
// Establish the main thread here.
322
rv = nsThreadManager::get().Init();
323
if (NS_WARN_IF(NS_FAILED(rv))) {
324
return rv;
325
}
326
327
// Init the SystemGroup for dispatching main thread runnables.
328
SystemGroup::InitStatic();
329
330
// Set up the timer globals/timer thread
331
rv = nsTimerImpl::Startup();
332
if (NS_WARN_IF(NS_FAILED(rv))) {
333
return rv;
334
}
335
336
#ifndef ANDROID
337
// If the locale hasn't already been setup by our embedder,
338
// get us out of the "C" locale and into the system
339
if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) {
340
setlocale(LC_ALL, "");
341
}
342
#endif
343
344
nsDirectoryService::RealInit();
345
346
bool value;
347
348
if (aBinDirectory) {
349
rv = aBinDirectory->IsDirectory(&value);
350
351
if (NS_SUCCEEDED(rv) && value) {
352
nsDirectoryService::gService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR,
353
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
NS_ShutdownAtomTable();
773
774
NS_IF_RELEASE(gDebug);
775
776
delete sIOThread;
777
sIOThread = nullptr;
778
779
delete sMessageLoop;
780
sMessageLoop = nullptr;
781
782
if (sCommandLineWasInitialized) {
783
CommandLine::Terminate();
784
sCommandLineWasInitialized = false;
785
}
786
787
delete sExitManager;
788
sExitManager = nullptr;
789
790
Omnijar::CleanUp();
791
792
BackgroundHangMonitor::Shutdown();
793
794
delete sMainHangMonitor;
795
sMainHangMonitor = nullptr;
796
797
NS_LogTerm();
798
799
return NS_OK;
800
}
801
802
} // namespace mozilla