Bug 1891340 - Part 1: Add parameters to customize the before and after icon tints...
[gecko.git] / ipc / glue / ProcessChild.cpp
blobfe727ffa66dbcd3f9c8843316f1f9e14b494f65c
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 "mozilla/ipc/ProcessChild.h"
9 #include "Endpoint.h"
10 #include "nsDebug.h"
12 #ifdef XP_WIN
13 # include <stdlib.h> // for _exit()
14 # include <synchapi.h>
15 #else
16 # include <unistd.h> // for _exit()
17 # include <time.h>
18 # include "base/eintr_wrapper.h"
19 # include "prenv.h"
20 #endif
22 #include "nsAppRunner.h"
23 #include "mozilla/AppShutdown.h"
24 #include "mozilla/ipc/IOThreadChild.h"
25 #include "mozilla/GeckoArgs.h"
27 namespace mozilla {
28 namespace ipc {
30 ProcessChild* ProcessChild::gProcessChild;
31 StaticMutex ProcessChild::gIPCShutdownStateLock;
32 nsCString ProcessChild::gIPCShutdownStateAnnotation;
34 static Atomic<bool> sExpectingShutdown(false);
36 ProcessChild::ProcessChild(ProcessId aParentPid, const nsID& aMessageChannelId)
37 : ChildProcess(new IOThreadChild(aParentPid)),
38 mUILoop(MessageLoop::current()),
39 mParentPid(aParentPid),
40 mMessageChannelId(aMessageChannelId) {
41 MOZ_ASSERT(mUILoop, "UILoop should be created by now");
42 MOZ_ASSERT(!gProcessChild, "should only be one ProcessChild");
43 CrashReporter::RegisterAnnotationNSCString(
44 CrashReporter::Annotation::IPCShutdownState,
45 &gIPCShutdownStateAnnotation);
46 gProcessChild = this;
49 /* static */
50 void ProcessChild::AddPlatformBuildID(std::vector<std::string>& aExtraArgs) {
51 nsCString parentBuildID(mozilla::PlatformBuildID());
52 geckoargs::sParentBuildID.Put(parentBuildID.get(), aExtraArgs);
55 /* static */
56 bool ProcessChild::InitPrefs(int aArgc, char* aArgv[]) {
57 Maybe<uint64_t> prefsHandle = Some(0);
58 Maybe<uint64_t> prefMapHandle = Some(0);
59 Maybe<uint64_t> prefsLen = geckoargs::sPrefsLen.Get(aArgc, aArgv);
60 Maybe<uint64_t> prefMapSize = geckoargs::sPrefMapSize.Get(aArgc, aArgv);
62 if (prefsLen.isNothing() || prefMapSize.isNothing()) {
63 return false;
66 #ifdef XP_WIN
67 prefsHandle = geckoargs::sPrefsHandle.Get(aArgc, aArgv);
68 prefMapHandle = geckoargs::sPrefMapHandle.Get(aArgc, aArgv);
70 if (prefsHandle.isNothing() || prefMapHandle.isNothing()) {
71 return false;
73 #endif
75 SharedPreferenceDeserializer deserializer;
76 return deserializer.DeserializeFromSharedMemory(*prefsHandle, *prefMapHandle,
77 *prefsLen, *prefMapSize);
80 #ifdef ENABLE_TESTS
81 // Allow tests to cause a synthetic delay/"hang" during child process
82 // shutdown by setting environment variables.
83 # ifdef XP_UNIX
84 static void ReallySleep(int aSeconds) {
85 struct ::timespec snooze = {aSeconds, 0};
86 HANDLE_EINTR(nanosleep(&snooze, &snooze));
88 # else
89 static void ReallySleep(int aSeconds) { ::Sleep(aSeconds * 1000); }
90 # endif // Unix/Win
91 static void SleepIfEnv(const char* aName) {
92 if (auto* value = PR_GetEnv(aName)) {
93 ReallySleep(atoi(value));
96 #else // not tests
97 static void SleepIfEnv(const char* aName) {}
98 #endif
100 ProcessChild::~ProcessChild() {
101 #ifdef NS_FREE_PERMANENT_DATA
102 // In this case, we won't early-exit and we'll wait indefinitely for
103 // child processes to terminate. This sleep is late enough that, in
104 // content processes, it won't block parent process shutdown, so
105 // we'll get into late IPC shutdown with processes still running.
106 SleepIfEnv("MOZ_TEST_CHILD_EXIT_HANG");
107 #endif
108 gIPCShutdownStateAnnotation = ""_ns;
109 gProcessChild = nullptr;
112 /* static */
113 void ProcessChild::NotifiedImpendingShutdown() {
114 sExpectingShutdown = true;
115 ProcessChild::AppendToIPCShutdownStateAnnotation(
116 "NotifiedImpendingShutdown"_ns);
119 /* static */
120 bool ProcessChild::ExpectingShutdown() { return sExpectingShutdown; }
122 /* static */
123 void ProcessChild::QuickExit() {
124 #ifndef NS_FREE_PERMANENT_DATA
125 // In this case, we're going to terminate the child process before
126 // we get to ~ProcessChild above (and terminate the parent process
127 // before the shutdown hook in ProcessWatcher). Instead, blocking
128 // earlier will let us exercise ProcessWatcher's kill timer.
129 SleepIfEnv("MOZ_TEST_CHILD_EXIT_HANG");
130 #endif
131 AppShutdown::DoImmediateExit();
134 UntypedEndpoint ProcessChild::TakeInitialEndpoint() {
135 return UntypedEndpoint{PrivateIPDLInterface{},
136 child_thread()->TakeInitialPort(), mMessageChannelId,
137 base::GetCurrentProcId(), mParentPid};
140 } // namespace ipc
141 } // namespace mozilla