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 "GPUProcessHost.h"
8 #include "chrome/common/process_watcher.h"
9 #include "gfxPlatform.h"
10 #include "mozilla/dom/ContentParent.h"
11 #include "mozilla/gfx/GPUChild.h"
12 #include "mozilla/gfx/Logging.h"
13 #include "mozilla/layers/SynchronousTask.h"
14 #include "mozilla/Preferences.h"
15 #include "mozilla/StaticPrefs_layers.h"
16 #include "VRGPUChild.h"
17 #include "mozilla/ipc/ProcessUtils.h"
18 #ifdef MOZ_WIDGET_ANDROID
19 # include "mozilla/java/GeckoProcessManagerWrappers.h"
27 GPUProcessHost::GPUProcessHost(Listener
* aListener
)
28 : GeckoChildProcessHost(GeckoProcessType_GPU
),
31 mLaunchPhase(LaunchPhase::Unlaunched
),
33 mShutdownRequested(false),
34 mChannelClosed(false) {
35 MOZ_COUNT_CTOR(GPUProcessHost
);
38 GPUProcessHost::~GPUProcessHost() { MOZ_COUNT_DTOR(GPUProcessHost
); }
40 bool GPUProcessHost::Launch(StringVector aExtraOpts
) {
41 MOZ_ASSERT(mLaunchPhase
== LaunchPhase::Unlaunched
);
42 MOZ_ASSERT(!mGPUChild
);
43 MOZ_ASSERT(!gfxPlatform::IsHeadless());
45 mPrefSerializer
= MakeUnique
<ipc::SharedPreferenceSerializer
>();
46 if (!mPrefSerializer
->SerializeToSharedMemory(GeckoProcessType_GPU
,
47 /* remoteType */ ""_ns
)) {
50 mPrefSerializer
->AddSharedPrefCmdLineArgs(*this, aExtraOpts
);
52 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
53 mSandboxLevel
= Preferences::GetInt("security.sandbox.gpu.level");
56 mLaunchPhase
= LaunchPhase::Waiting
;
57 mLaunchTime
= TimeStamp::Now();
59 if (!GeckoChildProcessHost::AsyncLaunch(aExtraOpts
)) {
60 mLaunchPhase
= LaunchPhase::Complete
;
61 mPrefSerializer
= nullptr;
67 bool GPUProcessHost::WaitForLaunch() {
68 if (mLaunchPhase
== LaunchPhase::Complete
) {
73 StaticPrefs::layers_gpu_process_startup_timeout_ms_AtStartup();
75 // If one of the following environment variables are set we can effectively
76 // ignore the timeout - as we can guarantee the compositor process will be
78 if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") ||
79 PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
83 // Our caller expects the connection to be finished after we return, so we
84 // immediately set up the IPDL actor and fire callbacks. The IO thread will
85 // still dispatch a notification to the main thread - we'll just ignore it.
86 bool result
= GeckoChildProcessHost::WaitUntilConnected(timeoutMs
);
87 InitAfterConnect(result
);
91 void GPUProcessHost::OnChannelConnected(base::ProcessId peer_pid
) {
92 MOZ_ASSERT(!NS_IsMainThread());
94 GeckoChildProcessHost::OnChannelConnected(peer_pid
);
96 // Post a task to the main thread. Take the lock because mTaskFactory is not
98 RefPtr
<Runnable
> runnable
;
100 MonitorAutoLock
lock(mMonitor
);
102 mTaskFactory
.NewRunnableMethod(&GPUProcessHost::OnChannelConnectedTask
);
104 NS_DispatchToMainThread(runnable
);
107 void GPUProcessHost::OnChannelConnectedTask() {
108 if (mLaunchPhase
== LaunchPhase::Waiting
) {
109 InitAfterConnect(true);
113 void GPUProcessHost::OnChannelErrorTask() {
114 if (mLaunchPhase
== LaunchPhase::Waiting
) {
115 InitAfterConnect(false);
119 static uint64_t sProcessTokenCounter
= 0;
121 void GPUProcessHost::InitAfterConnect(bool aSucceeded
) {
122 MOZ_ASSERT(mLaunchPhase
== LaunchPhase::Waiting
);
123 MOZ_ASSERT(!mGPUChild
);
125 mLaunchPhase
= LaunchPhase::Complete
;
126 mPrefSerializer
= nullptr;
129 mProcessToken
= ++sProcessTokenCounter
;
130 mGPUChild
= MakeRefPtr
<GPUChild
>(this);
131 DebugOnly
<bool> rv
= TakeInitialEndpoint().Bind(mGPUChild
.get());
136 #ifdef MOZ_WIDGET_ANDROID
137 nsCOMPtr
<nsIEventTarget
> launcherThread(GetIPCLauncher());
138 MOZ_ASSERT(launcherThread
);
139 layers::SynchronousTask
task(
140 "GeckoProcessManager::GetCompositorSurfaceManager");
142 launcherThread
->Dispatch(NS_NewRunnableFunction(
143 "GeckoProcessManager::GetCompositorSurfaceManager", [&]() {
144 layers::AutoCompleteTask
complete(&task
);
145 mCompositorSurfaceManager
=
146 java::GeckoProcessManager::GetCompositorSurfaceManager();
154 mListener
->OnProcessLaunchComplete(this);
158 void GPUProcessHost::Shutdown(bool aUnexpectedShutdown
) {
159 MOZ_ASSERT(!mShutdownRequested
);
164 // OnChannelClosed uses this to check if the shutdown was expected or
166 mShutdownRequested
= true;
168 if (aUnexpectedShutdown
) {
169 mGPUChild
->OnUnexpectedShutdown();
172 // The channel might already be closed if we got here unexpectedly.
173 if (!mChannelClosed
) {
174 if (VRGPUChild::IsCreated()) {
175 VRGPUChild::Get()->Close();
177 mGPUChild
->SendShutdownVR();
181 #ifndef NS_FREE_PERMANENT_DATA
182 // No need to communicate shutdown, the GPU process doesn't need to
183 // communicate anything back.
184 KillHard("NormalShutdown");
187 // If we're shutting down unexpectedly, we're in the middle of handling an
188 // ActorDestroy for PGPUChild, which is still on the stack. We'll return
189 // back to OnChannelClosed.
191 // Otherwise, we'll wait for OnChannelClose to be called whenever PGPUChild
192 // acknowledges shutdown.
199 void GPUProcessHost::OnChannelClosed() {
200 mChannelClosed
= true;
202 if (!mShutdownRequested
&& mListener
) {
203 // This is an unclean shutdown. Notify our listener that we're going away.
204 mListener
->OnProcessUnexpectedShutdown(this);
209 // Release the actor.
210 GPUChild::Destroy(std::move(mGPUChild
));
211 MOZ_ASSERT(!mGPUChild
);
214 void GPUProcessHost::KillHard(const char* aReason
) {
215 ProcessHandle handle
= GetChildProcessHandle();
216 if (!base::KillProcess(handle
, base::PROCESS_END_KILLED_BY_USER
)) {
217 NS_WARNING("failed to kill subprocess!");
223 uint64_t GPUProcessHost::GetProcessToken() const { return mProcessToken
; }
225 void GPUProcessHost::KillProcess() { KillHard("DiagnosticKill"); }
227 void GPUProcessHost::CrashProcess() { mGPUChild
->SendCrashProcess(); }
229 void GPUProcessHost::DestroyProcess() {
230 // Cancel all tasks. We don't want anything triggering after our caller
231 // expects this to go away.
233 MonitorAutoLock
lock(mMonitor
);
234 mTaskFactory
.RevokeAll();
237 GetCurrentSerialEventTarget()->Dispatch(
238 NS_NewRunnableFunction("DestroyProcessRunnable", [this] { Destroy(); }));
241 #ifdef MOZ_WIDGET_ANDROID
242 java::CompositorSurfaceManager::Param
243 GPUProcessHost::GetCompositorSurfaceManager() {
244 return mCompositorSurfaceManager
;
249 } // namespace mozilla