LCOV - code coverage report
Current view: top level - gfx/ipc - GPUProcessHost.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 100 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: sts=8 sw=2 ts=2 tw=99 et :
       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 "GPUProcessHost.h"
       8             : #include "chrome/common/process_watcher.h"
       9             : #include "gfxPrefs.h"
      10             : #include "mozilla/gfx/Logging.h"
      11             : #include "nsITimer.h"
      12             : #include "mozilla/Preferences.h"
      13             : 
      14             : namespace mozilla {
      15             : namespace gfx {
      16             : 
      17             : using namespace ipc;
      18             : 
      19           0 : GPUProcessHost::GPUProcessHost(Listener* aListener)
      20             :  : GeckoChildProcessHost(GeckoProcessType_GPU),
      21             :    mListener(aListener),
      22             :    mTaskFactory(this),
      23             :    mLaunchPhase(LaunchPhase::Unlaunched),
      24             :    mProcessToken(0),
      25             :    mShutdownRequested(false),
      26           0 :    mChannelClosed(false)
      27             : {
      28           0 :   MOZ_COUNT_CTOR(GPUProcessHost);
      29           0 : }
      30             : 
      31           0 : GPUProcessHost::~GPUProcessHost()
      32             : {
      33           0 :   MOZ_COUNT_DTOR(GPUProcessHost);
      34           0 : }
      35             : 
      36             : bool
      37           0 : GPUProcessHost::Launch()
      38             : {
      39           0 :   MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched);
      40           0 :   MOZ_ASSERT(!mGPUChild);
      41             : 
      42             : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
      43             :   mSandboxLevel = Preferences::GetInt("security.sandbox.gpu.level");
      44             : #endif
      45             : 
      46           0 :   mLaunchPhase = LaunchPhase::Waiting;
      47           0 :   mLaunchTime = TimeStamp::Now();
      48             : 
      49           0 :   if (!GeckoChildProcessHost::AsyncLaunch()) {
      50           0 :     mLaunchPhase = LaunchPhase::Complete;
      51           0 :     return false;
      52             :   }
      53           0 :   return true;
      54             : }
      55             : 
      56             : bool
      57           0 : GPUProcessHost::WaitForLaunch()
      58             : {
      59           0 :   if (mLaunchPhase == LaunchPhase::Complete) {
      60           0 :     return !!mGPUChild;
      61             :   }
      62             : 
      63           0 :   int32_t timeoutMs = gfxPrefs::GPUProcessTimeoutMs();
      64             : 
      65             :   // If one of the following environment variables are set we can effectively
      66             :   // ignore the timeout - as we can guarantee the compositor process will be terminated
      67           0 :   if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") || PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
      68           0 :     timeoutMs = 0;
      69             :   }
      70             : 
      71             :   // Our caller expects the connection to be finished after we return, so we
      72             :   // immediately set up the IPDL actor and fire callbacks. The IO thread will
      73             :   // still dispatch a notification to the main thread - we'll just ignore it.
      74           0 :   bool result = GeckoChildProcessHost::WaitUntilConnected(timeoutMs);
      75           0 :   InitAfterConnect(result);
      76           0 :   return result;
      77             : }
      78             : 
      79             : void
      80           0 : GPUProcessHost::OnChannelConnected(int32_t peer_pid)
      81             : {
      82           0 :   MOZ_ASSERT(!NS_IsMainThread());
      83             : 
      84           0 :   GeckoChildProcessHost::OnChannelConnected(peer_pid);
      85             : 
      86             :   // Post a task to the main thread. Take the lock because mTaskFactory is not
      87             :   // thread-safe.
      88           0 :   RefPtr<Runnable> runnable;
      89             :   {
      90           0 :     MonitorAutoLock lock(mMonitor);
      91           0 :     runnable = mTaskFactory.NewRunnableMethod(&GPUProcessHost::OnChannelConnectedTask);
      92             :   }
      93           0 :   NS_DispatchToMainThread(runnable);
      94           0 : }
      95             : 
      96             : void
      97           0 : GPUProcessHost::OnChannelError()
      98             : {
      99           0 :   MOZ_ASSERT(!NS_IsMainThread());
     100             : 
     101           0 :   GeckoChildProcessHost::OnChannelError();
     102             : 
     103             :   // Post a task to the main thread. Take the lock because mTaskFactory is not
     104             :   // thread-safe.
     105           0 :   RefPtr<Runnable> runnable;
     106             :   {
     107           0 :     MonitorAutoLock lock(mMonitor);
     108           0 :     runnable = mTaskFactory.NewRunnableMethod(&GPUProcessHost::OnChannelErrorTask);
     109             :   }
     110           0 :   NS_DispatchToMainThread(runnable);
     111           0 : }
     112             : 
     113             : void
     114           0 : GPUProcessHost::OnChannelConnectedTask()
     115             : {
     116           0 :   if (mLaunchPhase == LaunchPhase::Waiting) {
     117           0 :     InitAfterConnect(true);
     118             :   }
     119           0 : }
     120             : 
     121             : void
     122           0 : GPUProcessHost::OnChannelErrorTask()
     123             : {
     124           0 :   if (mLaunchPhase == LaunchPhase::Waiting) {
     125           0 :     InitAfterConnect(false);
     126             :   }
     127           0 : }
     128             : 
     129             : static uint64_t sProcessTokenCounter = 0;
     130             : 
     131             : void
     132           0 : GPUProcessHost::InitAfterConnect(bool aSucceeded)
     133             : {
     134           0 :   MOZ_ASSERT(mLaunchPhase == LaunchPhase::Waiting);
     135           0 :   MOZ_ASSERT(!mGPUChild);
     136             : 
     137           0 :   mLaunchPhase = LaunchPhase::Complete;
     138             : 
     139           0 :   if (aSucceeded) {
     140           0 :     mProcessToken = ++sProcessTokenCounter;
     141           0 :     mGPUChild = MakeUnique<GPUChild>(this);
     142             :     DebugOnly<bool> rv =
     143           0 :       mGPUChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
     144           0 :     MOZ_ASSERT(rv);
     145             : 
     146           0 :     mGPUChild->Init();
     147             :   }
     148             : 
     149           0 :   if (mListener) {
     150           0 :     mListener->OnProcessLaunchComplete(this);
     151             :   }
     152           0 : }
     153             : 
     154             : void
     155           0 : GPUProcessHost::Shutdown()
     156             : {
     157           0 :   MOZ_ASSERT(!mShutdownRequested);
     158             : 
     159           0 :   mListener = nullptr;
     160             : 
     161           0 :   if (mGPUChild) {
     162             :     // OnChannelClosed uses this to check if the shutdown was expected or
     163             :     // unexpected.
     164           0 :     mShutdownRequested = true;
     165             : 
     166             :     // The channel might already be closed if we got here unexpectedly.
     167           0 :     if (!mChannelClosed) {
     168           0 :       mGPUChild->Close();
     169             :     }
     170             : 
     171             : #ifndef NS_FREE_PERMANENT_DATA
     172             :     // No need to communicate shutdown, the GPU process doesn't need to
     173             :     // communicate anything back.
     174             :     KillHard("NormalShutdown");
     175             : #endif
     176             : 
     177             :     // If we're shutting down unexpectedly, we're in the middle of handling an
     178             :     // ActorDestroy for PGPUChild, which is still on the stack. We'll return
     179             :     // back to OnChannelClosed.
     180             :     //
     181             :     // Otherwise, we'll wait for OnChannelClose to be called whenever PGPUChild
     182             :     // acknowledges shutdown.
     183           0 :     return;
     184             :   }
     185             : 
     186           0 :   DestroyProcess();
     187             : }
     188             : 
     189             : void
     190           0 : GPUProcessHost::OnChannelClosed()
     191             : {
     192           0 :   if (!mShutdownRequested) {
     193             :     // This is an unclean shutdown. Notify our listener that we're going away.
     194           0 :     mChannelClosed = true;
     195           0 :     if (mListener) {
     196           0 :       mListener->OnProcessUnexpectedShutdown(this);
     197             :     }
     198             :   }
     199             : 
     200             :   // Release the actor.
     201           0 :   GPUChild::Destroy(Move(mGPUChild));
     202           0 :   MOZ_ASSERT(!mGPUChild);
     203             : 
     204             :   // If the owner of GPUProcessHost already requested shutdown, we can now
     205             :   // schedule destruction. Otherwise we must wait for someone to call
     206             :   // Shutdown. Note that GPUProcessManager calls Shutdown within
     207             :   // OnProcessUnexpectedShutdown.
     208           0 :   if (mShutdownRequested) {
     209           0 :     DestroyProcess();
     210             :   }
     211           0 : }
     212             : 
     213             : void
     214           0 : GPUProcessHost::KillHard(const char* aReason)
     215             : {
     216           0 :   ProcessHandle handle = GetChildProcessHandle();
     217           0 :   if (!base::KillProcess(handle, base::PROCESS_END_KILLED_BY_USER, false)) {
     218           0 :     NS_WARNING("failed to kill subprocess!");
     219             :   }
     220             : 
     221           0 :   SetAlreadyDead();
     222           0 : }
     223             : 
     224             : uint64_t
     225           0 : GPUProcessHost::GetProcessToken() const
     226             : {
     227           0 :   return mProcessToken;
     228             : }
     229             : 
     230             : static void
     231           0 : DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
     232             : {
     233             :   XRE_GetIOMessageLoop()->
     234           0 :     PostTask(mozilla::MakeAndAddRef<DeleteTask<GeckoChildProcessHost>>(aSubprocess));
     235           0 : }
     236             : 
     237             : void
     238           0 : GPUProcessHost::KillProcess()
     239             : {
     240           0 :   KillHard("DiagnosticKill");
     241           0 : }
     242             : 
     243             : void
     244           0 : GPUProcessHost::DestroyProcess()
     245             : {
     246             :   // Cancel all tasks. We don't want anything triggering after our caller
     247             :   // expects this to go away.
     248             :   {
     249           0 :     MonitorAutoLock lock(mMonitor);
     250           0 :     mTaskFactory.RevokeAll();
     251             :   }
     252             : 
     253             :   MessageLoop::current()->
     254           0 :     PostTask(NewRunnableFunction(DelayedDeleteSubprocess, this));
     255           0 : }
     256             : 
     257             : } // namespace gfx
     258             : } // namespace mozilla

Generated by: LCOV version 1.13