Bug 1834537 - Part 6: Simplify GCRuntime::checkAllocatorState a little r=sfink
[gecko.git] / ipc / glue / UtilityProcessChild.cpp
blobb64c20705b48886c7523e84dae608fe5b496ef40
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 #include "UtilityProcessChild.h"
8 #include "mozilla/ipc/UtilityProcessManager.h"
9 #include "mozilla/ipc/UtilityProcessSandboxing.h"
10 #include "mozilla/dom/ContentParent.h"
11 #include "mozilla/dom/JSOracleChild.h"
12 #include "mozilla/dom/MemoryReportRequest.h"
13 #include "mozilla/ipc/CrashReporterClient.h"
14 #include "mozilla/ipc/Endpoint.h"
15 #include "mozilla/AppShutdown.h"
16 #include "mozilla/Preferences.h"
17 #include "mozilla/RemoteDecoderManagerParent.h"
19 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
20 # include "mozilla/Sandbox.h"
21 #endif
23 #if defined(XP_OPENBSD) && defined(MOZ_SANDBOX)
24 # include "mozilla/SandboxSettings.h"
25 #endif
27 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
28 # include "mozilla/SandboxTestingChild.h"
29 #endif
31 #include "mozilla/Telemetry.h"
33 #if defined(XP_WIN)
34 # include "mozilla/WinDllServices.h"
35 # include "mozilla/dom/WindowsUtilsChild.h"
36 #endif
38 #include "nsDebugImpl.h"
39 #include "nsIXULRuntime.h"
40 #include "nsThreadManager.h"
41 #include "GeckoProfiler.h"
43 #include "mozilla/ipc/ProcessChild.h"
44 #include "mozilla/FOGIPC.h"
45 #include "mozilla/glean/GleanMetrics.h"
47 #include "mozilla/Services.h"
49 namespace mozilla::ipc {
51 using namespace layers;
53 static StaticMutex sUtilityProcessChildMutex;
54 static StaticRefPtr<UtilityProcessChild> sUtilityProcessChild
55 MOZ_GUARDED_BY(sUtilityProcessChildMutex);
57 UtilityProcessChild::UtilityProcessChild() : mChildStartTime(TimeStamp::Now()) {
58 nsDebugImpl::SetMultiprocessMode("Utility");
61 UtilityProcessChild::~UtilityProcessChild() = default;
63 /* static */
64 RefPtr<UtilityProcessChild> UtilityProcessChild::GetSingleton() {
65 MOZ_ASSERT(XRE_IsUtilityProcess());
66 if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownFinal)) {
67 return nullptr;
69 StaticMutexAutoLock lock(sUtilityProcessChildMutex);
70 if (!sUtilityProcessChild) {
71 sUtilityProcessChild = new UtilityProcessChild();
73 return sUtilityProcessChild;
76 /* static */
77 RefPtr<UtilityProcessChild> UtilityProcessChild::Get() {
78 StaticMutexAutoLock lock(sUtilityProcessChildMutex);
79 return sUtilityProcessChild;
82 bool UtilityProcessChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
83 const nsCString& aParentBuildID,
84 uint64_t aSandboxingKind) {
85 MOZ_ASSERT(NS_IsMainThread());
87 // Initialize the thread manager before starting IPC. Otherwise, messages
88 // may be posted to the main thread and we won't be able to process them.
89 if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
90 return false;
93 // Now it's safe to start IPC.
94 if (NS_WARN_IF(!aEndpoint.Bind(this))) {
95 return false;
98 // This must be checked before any IPDL message, which may hit sentinel
99 // errors due to parent and content processes having different
100 // versions.
101 MessageChannel* channel = GetIPCChannel();
102 if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID.get())) {
103 // We need to quit this process if the buildID doesn't match the parent's.
104 // This can occur when an update occurred in the background.
105 ipc::ProcessChild::QuickExit();
108 // Init crash reporter support.
109 ipc::CrashReporterClient::InitSingleton(this);
111 if (NS_FAILED(NS_InitMinimalXPCOM())) {
112 return false;
115 mSandbox = (SandboxingKind)aSandboxingKind;
117 // At the moment, only ORB uses JSContext in the
118 // Utility Process and ORB uses GENERIC_UTILITY
119 if (mSandbox == SandboxingKind::GENERIC_UTILITY) {
120 JS::DisableJitBackend();
121 if (!JS_Init()) {
122 return false;
124 #if defined(__OpenBSD__) && defined(MOZ_SANDBOX)
125 // Bug 1823458: delay pledge initialization, otherwise
126 // JS_Init triggers sysctl(KERN_PROC_ID) which isnt
127 // permitted with the current pledge.utility config
128 StartOpenBSDSandbox(GeckoProcessType_Utility, mSandbox);
129 #endif
132 profiler_set_process_name(nsCString("Utility Process"));
134 // Notify the parent process that we have finished our init and that it can
135 // now resolve the pending promise of process startup
136 SendInitCompleted();
138 PROFILER_MARKER_UNTYPED(
139 "UtilityProcessChild::SendInitCompleted", IPC,
140 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(mChildStartTime)));
142 RunOnShutdown(
143 [sandboxKind = mSandbox] {
144 StaticMutexAutoLock lock(sUtilityProcessChildMutex);
145 sUtilityProcessChild = nullptr;
146 if (sandboxKind == SandboxingKind::GENERIC_UTILITY) {
147 JS_ShutDown();
150 ShutdownPhase::XPCOMShutdownFinal);
152 return true;
155 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
156 extern "C" {
157 void CGSShutdownServerConnections();
159 #endif
161 mozilla::ipc::IPCResult UtilityProcessChild::RecvInit(
162 const Maybe<FileDescriptor>& aBrokerFd,
163 const bool& aCanRecordReleaseTelemetry,
164 const bool& aIsReadyForBackgroundProcessing) {
165 // Do this now (before closing WindowServer on macOS) to avoid risking
166 // blocking in GetCurrentProcess() called on that platform
167 mozilla::ipc::SetThisProcessName("Utility Process");
169 #if defined(MOZ_SANDBOX)
170 # if defined(XP_MACOSX)
171 // Close all current connections to the WindowServer. This ensures that the
172 // Activity Monitor will not label the content process as "Not responding"
173 // because it's not running a native event loop. See bug 1384336.
174 CGSShutdownServerConnections();
176 # elif defined(XP_LINUX)
177 int fd = -1;
178 if (aBrokerFd.isSome()) {
179 fd = aBrokerFd.value().ClonePlatformHandle().release();
182 SetUtilitySandbox(fd, mSandbox);
184 # endif // XP_MACOSX/XP_LINUX
185 #endif // MOZ_SANDBOX
187 #if defined(XP_WIN)
188 if (aCanRecordReleaseTelemetry) {
189 RefPtr<DllServices> dllSvc(DllServices::Get());
190 dllSvc->StartUntrustedModulesProcessor(aIsReadyForBackgroundProcessing);
192 #endif // defined(XP_WIN)
194 PROFILER_MARKER_UNTYPED(
195 "UtilityProcessChild::RecvInit", IPC,
196 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(mChildStartTime)));
197 return IPC_OK();
200 mozilla::ipc::IPCResult UtilityProcessChild::RecvPreferenceUpdate(
201 const Pref& aPref) {
202 Preferences::SetPreference(aPref);
203 return IPC_OK();
206 mozilla::ipc::IPCResult UtilityProcessChild::RecvInitProfiler(
207 Endpoint<PProfilerChild>&& aEndpoint) {
208 mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
209 return IPC_OK();
212 mozilla::ipc::IPCResult UtilityProcessChild::RecvRequestMemoryReport(
213 const uint32_t& aGeneration, const bool& aAnonymize,
214 const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile,
215 const RequestMemoryReportResolver& aResolver) {
216 nsPrintfCString processName("Utility (pid %" PRIPID
217 ", sandboxingKind %" PRIu64 ")",
218 base::GetCurrentProcId(), mSandbox);
220 mozilla::dom::MemoryReportRequestClient::Start(
221 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
222 [&](const MemoryReport& aReport) {
223 Unused << GetSingleton()->SendAddMemoryReport(aReport);
225 aResolver);
226 return IPC_OK();
229 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
230 mozilla::ipc::IPCResult UtilityProcessChild::RecvInitSandboxTesting(
231 Endpoint<PSandboxTestingChild>&& aEndpoint) {
232 if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
233 return IPC_FAIL(
234 this, "InitSandboxTesting failed to initialise the child process.");
236 return IPC_OK();
238 #endif
240 mozilla::ipc::IPCResult UtilityProcessChild::RecvFlushFOGData(
241 FlushFOGDataResolver&& aResolver) {
242 glean::FlushFOGData(std::move(aResolver));
243 return IPC_OK();
246 mozilla::ipc::IPCResult UtilityProcessChild::RecvTestTriggerMetrics(
247 TestTriggerMetricsResolver&& aResolve) {
248 mozilla::glean::test_only_ipc::a_counter.Add(
249 nsIXULRuntime::PROCESS_TYPE_UTILITY);
250 aResolve(true);
251 return IPC_OK();
254 mozilla::ipc::IPCResult UtilityProcessChild::RecvTestTelemetryProbes() {
255 const uint32_t kExpectedUintValue = 42;
256 Telemetry::ScalarSet(Telemetry::ScalarID::TELEMETRY_TEST_UTILITY_ONLY_UINT,
257 kExpectedUintValue);
258 return IPC_OK();
261 mozilla::ipc::IPCResult
262 UtilityProcessChild::RecvStartUtilityAudioDecoderService(
263 Endpoint<PUtilityAudioDecoderParent>&& aEndpoint) {
264 PROFILER_MARKER_UNTYPED(
265 "UtilityProcessChild::RecvStartUtilityAudioDecoderService", MEDIA,
266 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(mChildStartTime)));
267 mUtilityAudioDecoderInstance = new UtilityAudioDecoderParent();
268 if (!mUtilityAudioDecoderInstance) {
269 return IPC_FAIL(this, "Failing to create UtilityAudioDecoderParent");
272 mUtilityAudioDecoderInstance->Start(std::move(aEndpoint));
273 return IPC_OK();
276 mozilla::ipc::IPCResult UtilityProcessChild::RecvStartJSOracleService(
277 Endpoint<PJSOracleChild>&& aEndpoint) {
278 PROFILER_MARKER_UNTYPED(
279 "UtilityProcessChild::RecvStartJSOracleService", JS,
280 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(mChildStartTime)));
281 mJSOracleInstance = new mozilla::dom::JSOracleChild();
282 if (!mJSOracleInstance) {
283 return IPC_FAIL(this, "Failing to create JSOracleParent");
286 mJSOracleInstance->Start(std::move(aEndpoint));
287 return IPC_OK();
290 #if defined(XP_WIN)
291 mozilla::ipc::IPCResult UtilityProcessChild::RecvStartWindowsUtilsService(
292 Endpoint<dom::PWindowsUtilsChild>&& aEndpoint) {
293 PROFILER_MARKER_UNTYPED(
294 "UtilityProcessChild::RecvStartWindowsUtilsService", OTHER,
295 MarkerOptions(MarkerTiming::IntervalUntilNowFrom(mChildStartTime)));
296 mWindowsUtilsInstance = new dom::WindowsUtilsChild();
297 if (!mWindowsUtilsInstance) {
298 return IPC_FAIL(this, "Failed to create WindowsUtilsChild");
301 [[maybe_unused]] bool ok = std::move(aEndpoint).Bind(mWindowsUtilsInstance);
302 MOZ_ASSERT(ok);
303 return IPC_OK();
306 mozilla::ipc::IPCResult UtilityProcessChild::RecvGetUntrustedModulesData(
307 GetUntrustedModulesDataResolver&& aResolver) {
308 RefPtr<DllServices> dllSvc(DllServices::Get());
309 dllSvc->GetUntrustedModulesData()->Then(
310 GetMainThreadSerialEventTarget(), __func__,
311 [aResolver](Maybe<UntrustedModulesData>&& aData) {
312 aResolver(std::move(aData));
314 [aResolver](nsresult aReason) { aResolver(Nothing()); });
315 return IPC_OK();
318 mozilla::ipc::IPCResult
319 UtilityProcessChild::RecvUnblockUntrustedModulesThread() {
320 if (nsCOMPtr<nsIObserverService> obs =
321 mozilla::services::GetObserverService()) {
322 obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr);
324 return IPC_OK();
326 #endif // defined(XP_WIN)
328 void UtilityProcessChild::ActorDestroy(ActorDestroyReason aWhy) {
329 if (AbnormalShutdown == aWhy) {
330 NS_WARNING("Shutting down Utility process early due to a crash!");
331 ipc::ProcessChild::QuickExit();
334 // Send the last bits of Glean data over to the main process.
335 glean::FlushFOGData(
336 [](ByteBuf&& aBuf) { glean::SendFOGData(std::move(aBuf)); });
338 #ifndef NS_FREE_PERMANENT_DATA
339 ProcessChild::QuickExit();
340 #else
342 if (mProfilerController) {
343 mProfilerController->Shutdown();
344 mProfilerController = nullptr;
347 uint32_t timeout = 0;
348 if (mUtilityAudioDecoderInstance) {
349 mUtilityAudioDecoderInstance = nullptr;
350 timeout = 10 * 1000;
353 mJSOracleInstance = nullptr;
355 # ifdef XP_WIN
356 mWindowsUtilsInstance = nullptr;
357 # endif
359 // Wait until all RemoteDecoderManagerParent have closed.
360 // It is still possible some may not have clean up yet, and we might hit
361 // timeout. Our xpcom-shutdown listener should take care of cleaning the
362 // reference of our singleton.
364 // FIXME: Should move from using AsyncBlockers to proper
365 // nsIAsyncShutdownService once it is not JS, see bug 1760855
366 mShutdownBlockers.WaitUntilClear(timeout)->Then(
367 GetCurrentSerialEventTarget(), __func__, [&]() {
368 # ifdef XP_WIN
370 RefPtr<DllServices> dllSvc(DllServices::Get());
371 dllSvc->DisableFull();
373 # endif // defined(XP_WIN)
375 ipc::CrashReporterClient::DestroySingleton();
376 XRE_ShutdownChildProcess();
378 #endif // NS_FREE_PERMANENT_DATA
381 } // namespace mozilla::ipc