Wait for VideoDecoderManagerParents to shut down before destroying the VideoParent thread. (bug 1360697, r=billm)
authorDavid Anderson <danderson@mozilla.com>
Tue, 09 May 2017 16:51:07 -0700
changeset 357457 90cc6db6ad4a89bbfd10bec71528bc52ddf1a152
parent 357456 88bd4874e0bd7ebc0f6c47658e2c4c44cdeeae82
child 357458 3eaa4db163b9c297d750d8bf721fda72c945f94f
push id31792
push usercbook@mozilla.com
push dateWed, 10 May 2017 13:07:59 +0000
treeherdermozilla-central@ebbcdaa5b580 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1360697
milestone55.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
Wait for VideoDecoderManagerParents to shut down before destroying the VideoParent thread. (bug 1360697, r=billm)
dom/media/ipc/VideoDecoderManagerParent.cpp
dom/media/ipc/VideoDecoderManagerParent.h
--- a/dom/media/ipc/VideoDecoderManagerParent.cpp
+++ b/dom/media/ipc/VideoDecoderManagerParent.cpp
@@ -37,16 +37,33 @@ VideoDecoderManagerParent::StoreImage(Im
   mImageMap[aTexture->GetSerial()] = aImage;
   mTextureMap[aTexture->GetSerial()] = aTexture;
   return SurfaceDescriptorGPUVideo(aTexture->GetSerial());
 }
 
 StaticRefPtr<nsIThread> sVideoDecoderManagerThread;
 StaticRefPtr<TaskQueue> sManagerTaskQueue;
 
+class VideoDecoderManagerThreadHolder
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderManagerThreadHolder)
+
+public:
+  VideoDecoderManagerThreadHolder() {}
+
+private:
+  ~VideoDecoderManagerThreadHolder() {
+    NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
+      sVideoDecoderManagerThread->Shutdown();
+      sVideoDecoderManagerThread = nullptr;
+    }));
+  }
+};
+StaticRefPtr<VideoDecoderManagerThreadHolder> sVideoDecoderManagerThreadHolder;
+
 class ManagerThreadShutdownObserver : public nsIObserver
 {
   virtual ~ManagerThreadShutdownObserver() = default;
 public:
   ManagerThreadShutdownObserver() {}
 
   NS_DECL_ISUPPORTS
 
@@ -76,16 +93,17 @@ VideoDecoderManagerParent::StartupThread
   }
 
   RefPtr<nsIThread> managerThread;
   nsresult rv = NS_NewNamedThread("VideoParent", getter_AddRefs(managerThread));
   if (NS_FAILED(rv)) {
     return;
   }
   sVideoDecoderManagerThread = managerThread;
+  sVideoDecoderManagerThreadHolder = new VideoDecoderManagerThreadHolder();
 #if XP_WIN
   sVideoDecoderManagerThread->Dispatch(NS_NewRunnableFunction([]() {
     HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
     MOZ_ASSERT(hr == S_OK);
   }), NS_DISPATCH_NORMAL);
 #endif
   sVideoDecoderManagerThread->Dispatch(NS_NewRunnableFunction([]() {
     layers::VideoBridgeChild::Startup();
@@ -100,18 +118,20 @@ VideoDecoderManagerParent::StartupThread
 
 void
 VideoDecoderManagerParent::ShutdownThreads()
 {
   sManagerTaskQueue->BeginShutdown();
   sManagerTaskQueue->AwaitShutdownAndIdle();
   sManagerTaskQueue = nullptr;
 
-  sVideoDecoderManagerThread->Shutdown();
-  sVideoDecoderManagerThread = nullptr;
+  sVideoDecoderManagerThreadHolder = nullptr;
+  while (sVideoDecoderManagerThread) {
+    NS_ProcessNextEvent(nullptr, true);
+  }
 }
 
 void
 VideoDecoderManagerParent::ShutdownVideoBridge()
 {
   if (sVideoDecoderManagerThread) {
     RefPtr<Runnable> task = NS_NewRunnableFunction([]() {
       VideoBridgeChild::Shutdown();
@@ -132,34 +152,42 @@ VideoDecoderManagerParent::CreateForCont
   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
   MOZ_ASSERT(NS_IsMainThread());
 
   StartupThreads();
   if (!sVideoDecoderManagerThread) {
     return false;
   }
 
-  RefPtr<VideoDecoderManagerParent> parent = new VideoDecoderManagerParent();
+  RefPtr<VideoDecoderManagerParent> parent =
+    new VideoDecoderManagerParent(sVideoDecoderManagerThreadHolder);
 
   RefPtr<Runnable> task = NewRunnableMethod<Endpoint<PVideoDecoderManagerParent>&&>(
     parent, &VideoDecoderManagerParent::Open, Move(aEndpoint));
   sVideoDecoderManagerThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
   return true;
 }
 
-VideoDecoderManagerParent::VideoDecoderManagerParent()
+VideoDecoderManagerParent::VideoDecoderManagerParent(VideoDecoderManagerThreadHolder* aHolder)
+ : mThreadHolder(aHolder)
 {
   MOZ_COUNT_CTOR(VideoDecoderManagerParent);
 }
 
 VideoDecoderManagerParent::~VideoDecoderManagerParent()
 {
   MOZ_COUNT_DTOR(VideoDecoderManagerParent);
 }
 
+void
+VideoDecoderManagerParent::ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason)
+{
+  mThreadHolder = nullptr;
+}
+
 PVideoDecoderParent*
 VideoDecoderManagerParent::AllocPVideoDecoderParent(const VideoInfo& aVideoInfo,
                                                     const layers::TextureFactoryIdentifier& aIdentifier,
                                                     bool* aSuccess)
 {
   RefPtr<TaskQueue> decodeTaskQueue = new TaskQueue(
     SharedThreadPool::Get(NS_LITERAL_CSTRING("VideoDecoderParent"), 4),
     "VideoDecoderParent::mDecodeTaskQueue");
--- a/dom/media/ipc/VideoDecoderManagerParent.h
+++ b/dom/media/ipc/VideoDecoderManagerParent.h
@@ -6,16 +6,18 @@
 #ifndef include_dom_ipc_VideoDecoderManagerParent_h
 #define include_dom_ipc_VideoDecoderManagerParent_h
 
 #include "mozilla/dom/PVideoDecoderManagerParent.h"
 
 namespace mozilla {
 namespace dom {
 
+class VideoDecoderManagerThreadHolder;
+
 class VideoDecoderManagerParent final : public PVideoDecoderManagerParent
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderManagerParent)
 
   static bool CreateForContent(Endpoint<PVideoDecoderManagerParent>&& aEndpoint);
 
   // Can be called from any thread
@@ -30,26 +32,28 @@ public:
 
 protected:
   PVideoDecoderParent* AllocPVideoDecoderParent(const VideoInfo& aVideoInfo, const layers::TextureFactoryIdentifier& aIdentifier, bool* aSuccess) override;
   bool DeallocPVideoDecoderParent(PVideoDecoderParent* actor) override;
 
   mozilla::ipc::IPCResult RecvReadback(const SurfaceDescriptorGPUVideo& aSD, SurfaceDescriptor* aResult) override;
   mozilla::ipc::IPCResult RecvDeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD) override;
 
-  void ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override {}
+  void ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override;
 
   void DeallocPVideoDecoderManagerParent() override;
 
- private:
-  VideoDecoderManagerParent();
+private:
+  explicit VideoDecoderManagerParent(VideoDecoderManagerThreadHolder* aThreadHolder);
   ~VideoDecoderManagerParent();
 
   void Open(Endpoint<PVideoDecoderManagerParent>&& aEndpoint);
 
   std::map<uint64_t, RefPtr<layers::Image>> mImageMap;
   std::map<uint64_t, RefPtr<layers::TextureClient>> mTextureMap;
+
+  RefPtr<VideoDecoderManagerThreadHolder> mThreadHolder;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // include_dom_ipc_VideoDecoderManagerParent_h