Bug 1516554 - Part 7: Resolve MessageLoop destroy before VR IPC channels close issue. r=kip
authorDaosheng Mu <daoshengmu@gmail.com>
Fri, 11 Jan 2019 22:51:48 +0000
changeset 510944 829462dca3525998f3d038c935e6c3f8483cf12d
parent 510943 ffe71a987b8245db2873918f0aa00b6c8cb5c311
child 510945 850b70af2f47be4f8a0d72dc860f39d6ee7d9916
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskip
bugs1516554
milestone66.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 1516554 - Part 7: Resolve MessageLoop destroy before VR IPC channels close issue. r=kip Differential Revision: https://phabricator.services.mozilla.com/D16262
gfx/ipc/GPUProcessHost.cpp
gfx/vr/ipc/VRGPUChild.cpp
gfx/vr/ipc/VRGPUChild.h
gfx/vr/ipc/VRGPUParent.cpp
gfx/vr/ipc/VRGPUParent.h
gfx/vr/ipc/VRParent.cpp
gfx/vr/service/VRServiceManager.cpp
--- a/gfx/ipc/GPUProcessHost.cpp
+++ b/gfx/ipc/GPUProcessHost.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GPUProcessHost.h"
 #include "chrome/common/process_watcher.h"
 #include "gfxPrefs.h"
 #include "mozilla/gfx/Logging.h"
 #include "nsITimer.h"
 #include "mozilla/Preferences.h"
+#include "VRGPUChild.h"
 
 namespace mozilla {
 namespace gfx {
 
 using namespace ipc;
 
 GPUProcessHost::GPUProcessHost(Listener* aListener)
     : GeckoChildProcessHost(GeckoProcessType_GPU),
@@ -145,16 +146,19 @@ void GPUProcessHost::Shutdown() {
 
   if (mGPUChild) {
     // OnChannelClosed uses this to check if the shutdown was expected or
     // unexpected.
     mShutdownRequested = true;
 
     // The channel might already be closed if we got here unexpectedly.
     if (!mChannelClosed) {
+      if (VRGPUChild::IsCreated()) {
+        VRGPUChild::Get()->Close();
+      }
       mGPUChild->SendShutdownVR();
       mGPUChild->Close();
     }
 
 #ifndef NS_FREE_PERMANENT_DATA
     // No need to communicate shutdown, the GPU process doesn't need to
     // communicate anything back.
     KillHard("NormalShutdown");
--- a/gfx/vr/ipc/VRGPUChild.cpp
+++ b/gfx/vr/ipc/VRGPUChild.cpp
@@ -37,13 +37,24 @@ static StaticRefPtr<VRGPUChild> sVRGPUCh
 
 /* static */ VRGPUChild* VRGPUChild::Get() {
   MOZ_ASSERT(IsCreated(), "VRGPUChild haven't initialized yet.");
   return sVRGPUChildSingleton;
 }
 
 /*static*/ void VRGPUChild::Shutdown() {
   MOZ_ASSERT(NS_IsMainThread());
+  if (sVRGPUChildSingleton && !sVRGPUChildSingleton->IsClosed()) {
+    sVRGPUChildSingleton->Close();
+  }
   sVRGPUChildSingleton = nullptr;
 }
 
+void VRGPUChild::ActorDestroy(ActorDestroyReason aWhy) {
+  mClosed = true;
+}
+
+bool VRGPUChild::IsClosed() {
+  return mClosed;
+}
+
 }  // namespace gfx
 }  // namespace mozilla
--- a/gfx/vr/ipc/VRGPUChild.h
+++ b/gfx/vr/ipc/VRGPUChild.h
@@ -16,20 +16,25 @@ class VRGPUChild final : public PVRGPUCh
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRGPUChild);
 
   static VRGPUChild* Get();
   static bool InitForGPUProcess(Endpoint<PVRGPUChild>&& aEndpoint);
   static bool IsCreated();
   static void Shutdown();
 
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+  bool IsClosed();
+
  protected:
-  explicit VRGPUChild() {}
-  ~VRGPUChild() {}
+  explicit VRGPUChild() : mClosed(false) {}
+  ~VRGPUChild() = default;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(VRGPUChild);
+
+  bool mClosed;
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif  // GFX_VR_GPU_CHILD_H
\ No newline at end of file
--- a/gfx/vr/ipc/VRGPUParent.cpp
+++ b/gfx/vr/ipc/VRGPUParent.cpp
@@ -8,17 +8,18 @@
 
 #include "mozilla/ipc/ProcessChild.h"
 
 namespace mozilla {
 namespace gfx {
 
 using namespace ipc;
 
-VRGPUParent::VRGPUParent(ProcessId aChildProcessId) {
+VRGPUParent::VRGPUParent(ProcessId aChildProcessId)
+ : mClosed(false) {
   MOZ_COUNT_CTOR(VRGPUParent);
   MOZ_ASSERT(NS_IsMainThread());
 
   SetOtherProcessId(aChildProcessId);
 }
 
 VRGPUParent::~VRGPUParent() {
   MOZ_COUNT_DTOR(VRGPUParent);
@@ -27,30 +28,31 @@ VRGPUParent::~VRGPUParent() {
 void VRGPUParent::ActorDestroy(ActorDestroyReason aWhy) {
 #if !defined(MOZ_WIDGET_ANDROID)
   if (mVRService) {
     mVRService->Stop();
     mVRService = nullptr;
   }
 #endif
 
+  mClosed = true;
   MessageLoop::current()->PostTask(
       NewRunnableMethod("gfx::VRGPUParent::DeferredDestroy", this,
                         &VRGPUParent::DeferredDestroy));
 }
 
 void VRGPUParent::DeferredDestroy() { mSelfRef = nullptr; }
 
 /* static */ RefPtr<VRGPUParent> VRGPUParent::CreateForGPU(
     Endpoint<PVRGPUParent>&& aEndpoint) {
   RefPtr<VRGPUParent> vcp = new VRGPUParent(aEndpoint.OtherPid());
   MessageLoop::current()->PostTask(NewRunnableMethod<Endpoint<PVRGPUParent>&&>(
       "gfx::VRGPUParent::Bind", vcp, &VRGPUParent::Bind, std::move(aEndpoint)));
 
-  return vcp;
+  return vcp.forget();
 }
 
 void VRGPUParent::Bind(Endpoint<PVRGPUParent>&& aEndpoint) {
   if (!aEndpoint.Bind(this)) {
     return;
   }
 
   mSelfRef = this;
@@ -73,10 +75,14 @@ mozilla::ipc::IPCResult VRGPUParent::Rec
     mVRService->Stop();
     mVRService = nullptr;
   }
 #endif
 
   return IPC_OK();
 }
 
+bool VRGPUParent::IsClosed() {
+  return mClosed;
+}
+
 }  // namespace gfx
 }  // namespace mozilla
\ No newline at end of file
--- a/gfx/vr/ipc/VRGPUParent.h
+++ b/gfx/vr/ipc/VRGPUParent.h
@@ -14,16 +14,17 @@ namespace mozilla {
 namespace gfx {
 
 class VRGPUParent final : public PVRGPUParent {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRGPUParent)
 
  public:
   static RefPtr<VRGPUParent> CreateForGPU(Endpoint<PVRGPUParent>&& aEndpoint);
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+  bool IsClosed();
 
  protected:
 
   void Bind(Endpoint<PVRGPUParent>&& aEndpoint);
   virtual mozilla::ipc::IPCResult RecvStartVRService() override;
   virtual mozilla::ipc::IPCResult RecvStopVRService() override;
 
  private:
@@ -31,15 +32,17 @@ class VRGPUParent final : public PVRGPUP
   ~VRGPUParent();
 
   void DeferredDestroy();
 
   RefPtr<VRGPUParent> mSelfRef;
 #if !defined(MOZ_WIDGET_ANDROID)
   RefPtr<VRService> mVRService;
 #endif
+  bool mClosed;
+
   DISALLOW_COPY_AND_ASSIGN(VRGPUParent);
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif  // GFX_VR_CONTENT_PARENT_H
--- a/gfx/vr/ipc/VRParent.cpp
+++ b/gfx/vr/ipc/VRParent.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "VRParent.h"
 #include "VRGPUParent.h"
 #include "VRManager.h"
 #include "gfxConfig.h"
+#include "nsDebugImpl.h"
 
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/ipc/ProcessChild.h"
 
 #if defined(XP_WIN)
 #include "mozilla/gfx/DeviceManagerDx.h"
 #endif
 
@@ -91,16 +92,19 @@ mozilla::ipc::IPCResult VRParent::RecvOp
   return IPC_OK();
 }
 
 void VRParent::ActorDestroy(ActorDestroyReason aWhy) {
   if (AbnormalShutdown == aWhy) {
     NS_WARNING("Shutting down VR process early due to a crash!");
     ProcessChild::QuickExit();
   }
+  if (!mVRGPUParent->IsClosed()) {
+    mVRGPUParent->Close();
+  }
 
   mVRGPUParent = nullptr;
 #if defined(XP_WIN)
   DeviceManagerDx::Shutdown();
 #endif
   gfxVars::Shutdown();
   gfxConfig::Shutdown();
   gfxPrefs::DestroySingleton();
@@ -118,16 +122,18 @@ bool VRParent::Init(base::ProcessId aPar
     return false;
   }
 
   // Now it's safe to start IPC.
   if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
     return false;
   }
 
+  nsDebugImpl::SetMultiprocessMode("VR");
+
   // This must be checked before any IPDL message, which may hit sentinel
   // errors due to parent and content processes having different
   // versions.
   MessageChannel* channel = GetIPCChannel();
   if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
     // We need to quit this process if the buildID doesn't match the parent's.
     // This can occur when an update occurred in the background.
     ProcessChild::QuickExit();
--- a/gfx/vr/service/VRServiceManager.cpp
+++ b/gfx/vr/service/VRServiceManager.cpp
@@ -35,17 +35,19 @@ void VRServiceManager::CreateVRProcess()
 
   NS_DispatchToMainThread(task.forget());
 }
 
 void VRServiceManager::ShutdownVRProcess() {
   if (VRGPUChild::IsCreated()) {
     VRGPUChild* vrGPUChild = VRGPUChild::Get();
     vrGPUChild->SendStopVRService();
-    vrGPUChild->Close();
+    if (!vrGPUChild->IsClosed()) {
+      vrGPUChild->Close();
+    }
     VRGPUChild::Shutdown();
   }
   if (gfxPrefs::VRProcessEnabled()) {
     // Using PGPU channel to tell the main process
     // to shutdown VR process.
     gfx::GPUParent* gpu = GPUParent::GetSingleton();
     MOZ_ASSERT(gpu);
     Unused << gpu->SendShutdownVRProcess();