Bug 1321052 - Convert ProcessHangMonitor to use endpoints. r=billm draft
authorAndrew McCreight <continuation@gmail.com>
Thu, 05 Jan 2017 12:54:52 -0800
changeset 458721 65fa71984d9827c7cfa75c33981d76aba7933b14
parent 457660 2977ca1224525680cbfb5c3ce3018818b6dfd8f2
child 458724 f4e8543cefaa40b273f04c292e29e6a6a47c9e35
push id41029
push userbmo:continuation@gmail.com
push dateTue, 10 Jan 2017 22:44:39 +0000
reviewersbillm
bugs1321052
milestone53.0a1
Bug 1321052 - Convert ProcessHangMonitor to use endpoints. r=billm MozReview-Commit-ID: Ixj2b3ONLcc
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/ipc/ProcessHangMonitor.cpp
dom/ipc/ProcessHangMonitor.h
dom/ipc/ProcessHangMonitorIPC.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1245,16 +1245,23 @@ ContentChild::AllocPGMPServiceChild(mozi
 mozilla::ipc::IPCResult
 ContentChild::RecvGMPsChanged(nsTArray<GMPCapabilityData>&& capabilities)
 {
   GeckoMediaPluginServiceChild::UpdateGMPCapabilities(Move(capabilities));
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+ContentChild::RecvInitProcessHangMonitor(Endpoint<PProcessHangMonitorChild>&& aHangMonitor)
+{
+  CreateHangMonitorChild(Move(aHangMonitor));
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 ContentChild::RecvInitRendering(Endpoint<PCompositorBridgeChild>&& aCompositor,
                                 Endpoint<PImageBridgeChild>&& aImageBridge,
                                 Endpoint<PVRManagerChild>&& aVRBridge,
                                 Endpoint<PVideoDecoderManagerChild>&& aVideoManager)
 {
   if (!CompositorBridgeChild::InitForContent(Move(aCompositor))) {
     return IPC_FAIL_NO_REASON(this);
   }
@@ -1307,23 +1314,16 @@ ContentChild::RecvReinitRendering(Endpoi
 
 PBackgroundChild*
 ContentChild::AllocPBackgroundChild(Transport* aTransport,
                                     ProcessId aOtherProcess)
 {
   return BackgroundChild::Alloc(aTransport, aOtherProcess);
 }
 
-PProcessHangMonitorChild*
-ContentChild::AllocPProcessHangMonitorChild(Transport* aTransport,
-                                            ProcessId aOtherProcess)
-{
-  return CreateHangMonitorChild(aTransport, aOtherProcess);
-}
-
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
 
 #include <stdlib.h>
 
 static bool
 GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath, nsCString &aAppDir)
 {
   nsAutoCString appPath;
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -161,33 +161,32 @@ public:
   PGMPServiceChild*
   AllocPGMPServiceChild(mozilla::ipc::Transport* transport,
                         base::ProcessId otherProcess) override;
 
   mozilla::ipc::IPCResult
   RecvGMPsChanged(nsTArray<GMPCapabilityData>&& capabilities) override;
 
   mozilla::ipc::IPCResult
+  RecvInitProcessHangMonitor(Endpoint<PProcessHangMonitorChild>&& aHangMonitor) override;
+
+  mozilla::ipc::IPCResult
   RecvInitRendering(
     Endpoint<PCompositorBridgeChild>&& aCompositor,
     Endpoint<PImageBridgeChild>&& aImageBridge,
     Endpoint<PVRManagerChild>&& aVRBridge,
     Endpoint<PVideoDecoderManagerChild>&& aVideoManager) override;
 
   mozilla::ipc::IPCResult
   RecvReinitRendering(
     Endpoint<PCompositorBridgeChild>&& aCompositor,
     Endpoint<PImageBridgeChild>&& aImageBridge,
     Endpoint<PVRManagerChild>&& aVRBridge,
     Endpoint<PVideoDecoderManagerChild>&& aVideoManager) override;
 
-  PProcessHangMonitorChild*
-  AllocPProcessHangMonitorChild(Transport* aTransport,
-                                ProcessId aOtherProcess) override;
-
   virtual mozilla::ipc::IPCResult RecvSetProcessSandbox(const MaybeFileDesc& aBroker) override;
 
   PBackgroundChild*
   AllocPBackgroundChild(Transport* aTransport, ProcessId aOtherProcess)
                         override;
 
   virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
                                             const IPCTabContext& aContext,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1772,17 +1772,17 @@ ContentParent::LaunchSubprocess(ProcessP
      base::GetProcId(mSubprocess->GetChildProcessHandle()));
 
   InitInternal(aInitialPriority,
                true, /* Setup off-main thread compositing */
                true  /* Send registered chrome */);
 
   ContentProcessManager::GetSingleton()->AddContentProcess(this);
 
-  ProcessHangMonitor::AddProcess(this);
+  mHangMonitorActor = ProcessHangMonitor::AddProcess(this);
 
   // Set a reply timeout for CPOWs.
   SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 0));
 
   return true;
 }
 
 ContentParent::ContentParent(ContentParent* aOpener,
@@ -2472,24 +2472,16 @@ ContentParent::AllocPGMPServiceParent(mo
 
 PBackgroundParent*
 ContentParent::AllocPBackgroundParent(Transport* aTransport,
                                       ProcessId aOtherProcess)
 {
   return BackgroundParent::Alloc(this, aTransport, aOtherProcess);
 }
 
-PProcessHangMonitorParent*
-ContentParent::AllocPProcessHangMonitorParent(Transport* aTransport,
-                                              ProcessId aOtherProcess)
-{
-  mHangMonitorActor = CreateHangMonitorParent(this, aTransport, aOtherProcess);
-  return mHangMonitorActor;
-}
-
 mozilla::ipc::IPCResult
 ContentParent::RecvGetProcessAttributes(ContentParentId* aCpId,
                                         bool* aIsForBrowser)
 {
   *aCpId = mChildID;
   *aIsForBrowser = mIsForBrowser;
 
   return IPC_OK();
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -705,20 +705,16 @@ private:
   PGMPServiceParent*
   AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
                          base::ProcessId aOtherProcess) override;
 
   PBackgroundParent*
   AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess)
                          override;
 
-  PProcessHangMonitorParent*
-  AllocPProcessHangMonitorParent(Transport* aTransport,
-                                 ProcessId aOtherProcess) override;
-
   virtual mozilla::ipc::IPCResult RecvGetProcessAttributes(ContentParentId* aCpId,
                                                            bool* aIsForBrowser) override;
 
   virtual mozilla::ipc::IPCResult
   RecvGetXPCOMProcessAttributes(bool* aIsOffline,
                                 bool* aIsConnected,
                                 int32_t* aCaptivePortalState,
                                 bool* aIsLangRTL,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -342,17 +342,16 @@ struct GMPCapabilityData
     nsCString version;
     GMPAPITags[] capabilities;
 };
 
 nested(upto inside_cpow) sync protocol PContent
 {
     parent spawns PPluginModule;
 
-    parent opens PProcessHangMonitor;
     parent opens PGMPService;
     child opens PBackground;
 
     manages PBlob;
     manages PBrowser;
     manages PContentPermissionRequest;
     manages PCrashReporter;
     manages PCycleCollectWithLogs;
@@ -410,16 +409,18 @@ both:
     // For parent->child, aBrowser must be non-null; aOuterWindowID can
     // be 0 to indicate the browser's current root document, or nonzero
     // to persist a subdocument.  For child->parent, arguments are
     // ignored and should be null/zero.
     async PWebBrowserPersistDocument(nullable PBrowser aBrowser,
                                      uint64_t aOuterWindowID);
 
 child:
+    async InitProcessHangMonitor(Endpoint<PProcessHangMonitorChild> hangMonitor);
+
     // Give the content process its endpoints to the compositor.
     async InitRendering(
       Endpoint<PCompositorBridgeChild> compositor,
       Endpoint<PImageBridgeChild> imageBridge,
       Endpoint<PVRManagerChild> vr,
       Endpoint<PVideoDecoderManagerChild> video);
 
     // Re-create the rendering stack using the given endpoints. This is sent
--- a/dom/ipc/ProcessHangMonitor.cpp
+++ b/dom/ipc/ProcessHangMonitor.cpp
@@ -36,16 +36,17 @@
 
 #ifdef XP_WIN
 // For IsDebuggerPresent()
 #include <windows.h>
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
+using namespace mozilla::ipc;
 
 /*
  * Basic architecture:
  *
  * Each process has its own ProcessHangMonitor singleton. This singleton exists
  * as long as there is at least one content process in the system. Each content
  * process has a HangMonitorChild and the chrome process has one
  * HangMonitorParent per process. Each process (including the chrome process)
@@ -73,18 +74,17 @@ namespace {
 
 class HangMonitorChild
   : public PProcessHangMonitorChild
 {
  public:
   explicit HangMonitorChild(ProcessHangMonitor* aMonitor);
   ~HangMonitorChild() override;
 
-  void Open(Transport* aTransport, ProcessId aOtherPid,
-            MessageLoop* aIOLoop);
+  void Bind(Endpoint<PProcessHangMonitorChild>&& aEndpoint);
 
   typedef ProcessHangMonitor::SlowScriptAction SlowScriptAction;
   SlowScriptAction NotifySlowScript(nsITabChild* aTabChild,
                                     const char* aFileName,
                                     unsigned aLineNo);
   void NotifySlowScriptAsync(TabId aTabId,
                              const nsCString& aFileName,
                              unsigned aLineNo);
@@ -206,17 +206,17 @@ private:
 
 class HangMonitorParent
   : public PProcessHangMonitorParent
 {
 public:
   explicit HangMonitorParent(ProcessHangMonitor* aMonitor);
   ~HangMonitorParent() override;
 
-  void Open(Transport* aTransport, ProcessId aPid, MessageLoop* aIOLoop);
+  void Bind(Endpoint<PProcessHangMonitorParent>&& aEndpoint);
 
   mozilla::ipc::IPCResult RecvHangEvidence(const HangData& aHangData) override;
   mozilla::ipc::IPCResult RecvClearHang() override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   void SetProcess(HangMonitoredProcess* aProcess) { mProcess = aProcess; }
 
@@ -411,25 +411,24 @@ HangMonitorChild::ClearForcePaint()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(XRE_IsContentProcess());
 
   mForcePaintMonitor->NotifyWait();
 }
 
 void
-HangMonitorChild::Open(Transport* aTransport, ProcessId aPid,
-                       MessageLoop* aIOLoop)
+HangMonitorChild::Bind(Endpoint<PProcessHangMonitorChild>&& aEndpoint)
 {
   MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
 
   MOZ_ASSERT(!sInstance);
   sInstance = this;
 
-  DebugOnly<bool> ok = PProcessHangMonitorChild::Open(aTransport, aPid, aIOLoop);
+  DebugOnly<bool> ok = aEndpoint.Bind(this);
   MOZ_ASSERT(ok);
 }
 
 void
 HangMonitorChild::NotifySlowScriptAsync(TabId aTabId,
                                         const nsCString& aFileName,
                                         unsigned aLineNo)
 {
@@ -630,22 +629,21 @@ HangMonitorParent::ForcePaintOnThread(Ta
 void
 HangMonitorParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
   mIPCOpen = false;
 }
 
 void
-HangMonitorParent::Open(Transport* aTransport, ProcessId aPid,
-                        MessageLoop* aIOLoop)
+HangMonitorParent::Bind(Endpoint<PProcessHangMonitorParent>&& aEndpoint)
 {
   MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
 
-  DebugOnly<bool> ok = PProcessHangMonitorParent::Open(aTransport, aPid, aIOLoop);
+  DebugOnly<bool> ok = aEndpoint.Bind(this);
   MOZ_ASSERT(ok);
 }
 
 class HangObserverNotifier final : public Runnable
 {
 public:
   HangObserverNotifier(HangMonitoredProcess* aProcess,
                        HangMonitorParent *aParent,
@@ -1168,79 +1166,86 @@ ProcessHangMonitor::InitiateCPOWTimeout(
 
 void
 ProcessHangMonitor::NotifyPluginHang(uint32_t aPluginId)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   return HangMonitorChild::Get()->NotifyPluginHang(aPluginId);
 }
 
-PProcessHangMonitorParent*
-mozilla::CreateHangMonitorParent(ContentParent* aContentParent,
-                                 mozilla::ipc::Transport* aTransport,
-                                 base::ProcessId aOtherPid)
+static PProcessHangMonitorParent*
+CreateHangMonitorParent(ContentParent* aContentParent,
+                        Endpoint<PProcessHangMonitorParent>&& aEndpoint)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
   auto* parent = new HangMonitorParent(monitor);
 
   auto* process = new HangMonitoredProcess(parent, aContentParent);
   parent->SetProcess(process);
 
   monitor->MonitorLoop()->PostTask(NewNonOwningRunnableMethod
-                                   <mozilla::ipc::Transport*,
-                                    base::ProcessId,
-                                    MessageLoop*>(parent,
-                                                  &HangMonitorParent::Open,
-                                                  aTransport, aOtherPid,
-                                                  XRE_GetIOMessageLoop()));
+                                   <Endpoint<PProcessHangMonitorParent>&&>(parent,
+                                                                           &HangMonitorParent::Bind,
+                                                                           Move(aEndpoint)));
 
   return parent;
 }
 
-PProcessHangMonitorChild*
-mozilla::CreateHangMonitorChild(mozilla::ipc::Transport* aTransport,
-                                base::ProcessId aOtherPid)
+void
+mozilla::CreateHangMonitorChild(Endpoint<PProcessHangMonitorChild>&& aEndpoint)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   JSContext* cx = danger::GetJSContext();
   JS_AddInterruptCallback(cx, InterruptCallback);
   JS::AddGCInterruptCallback(cx, InterruptCallback);
 
   ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
   auto* child = new HangMonitorChild(monitor);
 
   monitor->MonitorLoop()->PostTask(NewNonOwningRunnableMethod
-                                   <mozilla::ipc::Transport*,
-                                    base::ProcessId,
-                                    MessageLoop*>(child,
-                                                  &HangMonitorChild::Open,
-                                                  aTransport, aOtherPid,
-                                                  XRE_GetIOMessageLoop()));
-
-  return child;
+                                   <Endpoint<PProcessHangMonitorChild>&&>(child,
+                                                                          &HangMonitorChild::Bind,
+                                                                          Move(aEndpoint)));
 }
 
 MessageLoop*
 ProcessHangMonitor::MonitorLoop()
 {
   return mThread->message_loop();
 }
 
-/* static */ void
+/* static */ PProcessHangMonitorParent*
 ProcessHangMonitor::AddProcess(ContentParent* aContentParent)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
-  if (mozilla::Preferences::GetBool("dom.ipc.processHangMonitor", false)) {
-    DebugOnly<bool> opened = PProcessHangMonitor::Open(aContentParent);
-    MOZ_ASSERT(opened);
+  if (!mozilla::Preferences::GetBool("dom.ipc.processHangMonitor", false)) {
+    return nullptr;
   }
+
+  Endpoint<PProcessHangMonitorParent> parent;
+  Endpoint<PProcessHangMonitorChild> child;
+  nsresult rv;
+  rv = PProcessHangMonitor::CreateEndpoints(base::GetCurrentProcId(),
+                                            aContentParent->OtherPid(),
+                                            &parent, &child);
+  if (NS_FAILED(rv)) {
+    MOZ_ASSERT(false, "PProcessHangMonitor::CreateEndpoints failed");
+    return nullptr;
+  }
+
+  if (!aContentParent->SendInitProcessHangMonitor(Move(child))) {
+    MOZ_ASSERT(false);
+    return nullptr;
+  }
+
+  return CreateHangMonitorParent(aContentParent, Move(parent));
 }
 
 /* static */ void
 ProcessHangMonitor::RemoveProcess(PProcessHangMonitorParent* aParent)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   auto parent = static_cast<HangMonitorParent*>(aParent);
   parent->Shutdown();
--- a/dom/ipc/ProcessHangMonitor.h
+++ b/dom/ipc/ProcessHangMonitor.h
@@ -36,17 +36,17 @@ class ProcessHangMonitor final
 
  public:
   static ProcessHangMonitor* Get() { return sInstance; }
   static ProcessHangMonitor* GetOrCreate();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
-  static void AddProcess(dom::ContentParent* aContentParent);
+  static PProcessHangMonitorParent* AddProcess(dom::ContentParent* aContentParent);
   static void RemoveProcess(PProcessHangMonitorParent* aParent);
 
   static void ClearHang();
 
   static void ForcePaint(PProcessHangMonitorParent* aParent,
                          dom::TabParent* aTab,
                          uint64_t aLayerObserverEpoch);
   static void ClearForcePaint();
--- a/dom/ipc/ProcessHangMonitorIPC.h
+++ b/dom/ipc/ProcessHangMonitorIPC.h
@@ -15,20 +15,14 @@
 #include "mozilla/PProcessHangMonitorChild.h"
 
 namespace mozilla {
 
 namespace dom {
 class ContentParent;
 } // namespace dom
 
-PProcessHangMonitorParent*
-CreateHangMonitorParent(mozilla::dom::ContentParent* aContentParent,
-                        mozilla::ipc::Transport* aTransport,
-                        base::ProcessId aOtherProcess);
-
-PProcessHangMonitorChild*
-CreateHangMonitorChild(mozilla::ipc::Transport* aTransport,
-                       base::ProcessId aOtherProcess);
+void
+CreateHangMonitorChild(ipc::Endpoint<PProcessHangMonitorChild>&& aEndpoint);
 
 } // namespace mozilla
 
 #endif // mozilla_ProcessHangMonitorIPC_h