Bug 1314426 - Add a method to nsIDOMWindowUtils to terminate the GPU process and get the GPU process pid r=smaug,dvander
authorGeorge Wright <george@mozilla.com>
Mon, 31 Oct 2016 15:44:40 -0400
changeset 321449 131019a5ba42fa6a492e44a20f90c37dd8e5427b
parent 321448 cceb2a87580748749fb0932fa4f553b1e60ee8c4
child 321450 7157478b9a48d4a6f49fc5de16cac244caf84ea3
push id30928
push userphilringnalda@gmail.com
push dateTue, 08 Nov 2016 04:38:37 +0000
treeherdermozilla-central@f13e90d496cf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, dvander
bugs1314426
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1314426 - Add a method to nsIDOMWindowUtils to terminate the GPU process and get the GPU process pid r=smaug,dvander
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
gfx/ipc/GPUProcessHost.cpp
gfx/ipc/GPUProcessHost.h
gfx/ipc/GPUProcessManager.cpp
gfx/ipc/GPUProcessManager.h
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -105,16 +105,17 @@
 #include "nsCSSPseudoElements.h"            // for CSSPseudoElementType
 #include "nsNetUtil.h"
 #include "nsDocument.h"
 #include "HTMLImageElement.h"
 #include "mozilla/css/ImageLoader.h"
 #include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
 #include "mozilla/dom/Promise.h"
 #include "mozilla/StyleSheetInlines.h"
+#include "mozilla/gfx/GPUProcessManager.h"
 
 #ifdef XP_WIN
 #undef GetClassName
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
@@ -4087,16 +4088,39 @@ nsDOMWindowUtils::ForceReflowInterrupt()
   nsPresContext* pc = GetPresContext();
   if (!pc) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   pc->SetPendingInterruptFromTest();
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMWindowUtils::TerminateGPUProcess()
+{
+  GPUProcessManager* pm = GPUProcessManager::Get();
+  if (pm) {
+    pm->KillProcess();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMWindowUtils::GetGpuProcessPid(int32_t* aPid)
+{
+  GPUProcessManager* pm = GPUProcessManager::Get();
+  if (pm) {
+    *aPid = pm->GPUProcessPid();
+  } else {
+    *aPid = -1;
+  }
+
+  return NS_OK;
+}
+
 NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsTranslationNodeList)
 NS_IMPL_RELEASE(nsTranslationNodeList)
 
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -44,17 +44,17 @@ interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsITranslationNodeList;
 interface nsIJSRAIIHelper;
 interface nsIContentPermissionRequest;
 interface nsIObserver;
 
-[scriptable, uuid(46b44e33-13c2-4eb3-bf80-76a4e0857ccc)]
+[scriptable, uuid(c471d440-004b-4c50-a6f2-747db5f443b6)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1960,16 +1960,26 @@ interface nsIDOMWindowUtils : nsISupport
   void respectDisplayPortSuppression(in boolean aEnabled);
 
   /**
    * Set a flag that forces the next reflow interrupt check to return true. This
    * can be used by tests to force execution of the interrupted reflow codepaths.
    */
   void forceReflowInterrupt();
 
+  /**
+   * Terminate the GPU process. Used for testing GPU process restarts.
+   */
+  void terminateGPUProcess();
+
+  /**
+    * Returns the GPU process pid, or -1 if there is no GPU process.
+    */
+  readonly attribute int32_t gpuProcessPid;
+
   const long MOUSE_BUTTONS_NO_BUTTON = 0x00;
   const long MOUSE_BUTTONS_LEFT_BUTTON = 0x01;
   const long MOUSE_BUTTONS_RIGHT_BUTTON = 0x02;
   const long MOUSE_BUTTONS_MIDDLE_BUTTON = 0x04;
   // Typically, "back" button being left side of 5-button
   // mice, see "buttons" attribute document of DOM3 Events.
   const long MOUSE_BUTTONS_4TH_BUTTON = 0x08;
   // Typically, "forward" button being right side of 5-button
--- a/gfx/ipc/GPUProcessHost.cpp
+++ b/gfx/ipc/GPUProcessHost.cpp
@@ -219,16 +219,22 @@ GPUProcessHost::GetProcessToken() const
 static void
 DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
 {
   XRE_GetIOMessageLoop()->
     PostTask(mozilla::MakeAndAddRef<DeleteTask<GeckoChildProcessHost>>(aSubprocess));
 }
 
 void
+GPUProcessHost::KillProcess()
+{
+  KillHard("DiagnosticKill");
+}
+
+void
 GPUProcessHost::DestroyProcess()
 {
   // Cancel all tasks. We don't want anything triggering after our caller
   // expects this to go away.
   {
     MonitorAutoLock lock(mMonitor);
     mTaskFactory.RevokeAll();
   }
--- a/gfx/ipc/GPUProcessHost.h
+++ b/gfx/ipc/GPUProcessHost.h
@@ -91,16 +91,19 @@ public:
   }
 
   // Called on the IO thread.
   void OnChannelConnected(int32_t peer_pid) override;
   void OnChannelError() override;
 
   void SetListener(Listener* aListener);
 
+  // Used for tests and diagnostics
+  void KillProcess();
+
 private:
   // Called on the main thread.
   void OnChannelConnectedTask();
   void OnChannelErrorTask();
 
   // Called on the main thread after a connection has been established.
   void InitAfterConnect(bool aSucceeded);
 
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -382,16 +382,26 @@ GPUProcessManager::NotifyRemoteActorDest
 void
 GPUProcessManager::CleanShutdown()
 {
   DestroyProcess();
   mVsyncIOThread = nullptr;
 }
 
 void
+GPUProcessManager::KillProcess()
+{
+  if (!mProcess) {
+    return;
+  }
+
+  mProcess->KillProcess();
+}
+
+void
 GPUProcessManager::DestroyProcess()
 {
   if (!mProcess) {
     return;
   }
 
   mProcess->Shutdown();
   mProcessToken = 0;
@@ -601,16 +611,25 @@ GPUProcessManager::CreateContentImageBri
       return false;
     }
   }
 
   *aOutEndpoint = Move(childPipe);
   return true;
 }
 
+base::ProcessId
+GPUProcessManager::GPUProcessPid()
+{
+  base::ProcessId gpuPid = mGPUChild
+                           ? mGPUChild->OtherPid()
+                           : -1;
+  return gpuPid;
+}
+
 bool
 GPUProcessManager::CreateContentVRManager(base::ProcessId aOtherProcess,
                                           ipc::Endpoint<PVRManagerChild>* aOutEndpoint)
 {
   EnsureVRManager();
 
   base::ProcessId gpuPid = mGPUChild
                            ? mGPUChild->OtherPid()
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -128,16 +128,22 @@ public:
 
   void AddListener(GPUProcessListener* aListener);
   void RemoveListener(GPUProcessListener* aListener);
 
   // Send a message to the GPU process observer service to broadcast. Returns
   // true if the message was sent, false if not.
   bool NotifyGpuObservers(const char* aTopic);
 
+  // Used for tests and diagnostics
+  void KillProcess();
+
+  // Returns -1 if there is no GPU process, or the platform pid for it.
+  base::ProcessId GPUProcessPid();
+
   // Returns access to the PGPU protocol if a GPU process is present.
   GPUChild* GetGPUChild() {
     return mGPUChild;
   }
 
   // Returns whether or not a GPU process was ever launched.
   bool AttemptedGPUProcess() const {
     return mNumProcessAttempts > 0;