Backed out changesets 74ef5120ae2f and d26dfd37031a (bug 924622) for frequent Android and OSX crashes.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 30 Apr 2014 13:21:07 -0400
changeset 181449 a6864d25a859d0918bd52e12f409d8247edd9d35
parent 181448 b850412044d73daf27778fe93b28d6fe2b92d5af
child 181450 34887cdb561622ec80c4d80e249a87224be9b553
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
bugs924622
milestone32.0a1
backs out74ef5120ae2f590d8b766806025610f200ca3c8a
d26dfd37031a884671ac9ce57d6cc62d8463be3c
Backed out changesets 74ef5120ae2f and d26dfd37031a (bug 924622) for frequent Android and OSX crashes. CLOSED TREE
CLOBBER
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/ImageBridgeParent.cpp
gfx/layers/ipc/ImageBridgeParent.h
gfx/layers/ipc/PImageBridge.ipdl
gfx/thebes/gfxPlatform.cpp
xpcom/build/nsXPComInit.cpp
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 958889 moves files into the new mobile/android/base/tabspanel/ package.
+Bug 852935 - Android builds aren't picking up the Gamepad WebIDL changes.
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -161,53 +161,36 @@ ImageBridgeChild::UpdatePictureRect(Comp
 }
 
 // Singleton
 static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton;
 static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
 static Thread *sImageBridgeChildThread = nullptr;
 
 // dispatched function
-static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
+static void StopImageBridgeSync(ReentrantMonitor *aBarrier, bool *aDone)
 {
   ReentrantMonitorAutoEnter autoMon(*aBarrier);
 
   NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                     "Should be in ImageBridgeChild thread.");
   if (sImageBridgeChildSingleton) {
-    // Force all managed protocols to shut themselves down cleanly
-    InfallibleTArray<PCompositableChild*> compositables;
-    sImageBridgeChildSingleton->ManagedPCompositableChild(compositables);
-    for (int i = compositables.Length() - 1; i >= 0; --i) {
-      CompositableClient::FromIPDLActor(compositables[i])->Destroy();
-    }
-    InfallibleTArray<PTextureChild*> textures;
-    sImageBridgeChildSingleton->ManagedPTextureChild(textures);
-    for (int i = textures.Length() - 1; i >= 0; --i) {
-      TextureClient::AsTextureClient(textures[i])->ForceRemove();
-    }
-    sImageBridgeChildSingleton->SendWillStop();
-    sImageBridgeChildSingleton->MarkShutDown();
-    // From now on, no message can be sent through the image bridge from the
-    // client side except the final Stop message.
+    sImageBridgeChildSingleton->SendStop();
   }
   *aDone = true;
   aBarrier->NotifyAll();
 }
 
 // dispatched function
-static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone)
+static void DeleteImageBridgeSync(ReentrantMonitor *aBarrier, bool *aDone)
 {
   ReentrantMonitorAutoEnter autoMon(*aBarrier);
 
   NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                     "Should be in ImageBridgeChild thread.");
-
-  sImageBridgeChildSingleton->SendStop();
-
   sImageBridgeChildSingleton = nullptr;
   sImageBridgeParentSingleton = nullptr;
   *aDone = true;
   aBarrier->NotifyAll();
 }
 
 // dispatched function
 static void CreateImageClientSync(RefPtr<ImageClient>* result,
@@ -262,48 +245,38 @@ static void AllocGrallocBufferSync(const
 static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * parent)
 {
   MessageLoop *parentMsgLoop = parent->GetMessageLoop();
   ipc::MessageChannel *parentChannel = parent->GetIPCChannel();
   child->Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
 }
 
 ImageBridgeChild::ImageBridgeChild()
-  : mShuttingDown(false)
 {
   mTxn = new CompositableTransaction();
 }
 ImageBridgeChild::~ImageBridgeChild()
 {
   delete mTxn;
 }
 
 void
-ImageBridgeChild::MarkShutDown()
-{
-  MOZ_ASSERT(!mShuttingDown);
-  mShuttingDown = true;
-}
-
-void
 ImageBridgeChild::Connect(CompositableClient* aCompositable)
 {
   MOZ_ASSERT(aCompositable);
-  MOZ_ASSERT(!mShuttingDown);
   uint64_t id = 0;
   PCompositableChild* child =
     SendPCompositableConstructor(aCompositable->GetTextureInfo(), &id);
   MOZ_ASSERT(child);
   aCompositable->InitIPDLActor(child, id);
 }
 
 PCompositableChild*
 ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo, uint64_t* aID)
 {
-  MOZ_ASSERT(!mShuttingDown);
   return CompositableClient::CreateIPDLActor();
 }
 
 bool
 ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor)
 {
   return CompositableClient::DestroyIPDLActor(aActor);
 }
@@ -357,52 +330,30 @@ static void ReleaseImageClientNow(ImageC
 {
   MOZ_ASSERT(InImageBridgeChildThread());
   aClient->Release();
 }
 
 // static
 void ImageBridgeChild::DispatchReleaseImageClient(ImageClient* aClient)
 {
-  if (!IsCreated()) {
-    // CompositableClient::Release should normally happen in the ImageBridgeChild
-    // thread because it usually generate some IPDL messages.
-    // However, if we take this branch it means that the ImageBridgeChild
-    // has already shut down, along with the CompositableChild, which means no
-    // message will be sent and it is safe to run this code from any thread.
-    MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
-    aClient->Release();
-    return;
-  }
-
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction(&ReleaseImageClientNow, aClient));
 }
 
 static void ReleaseTextureClientNow(TextureClient* aClient)
 {
   MOZ_ASSERT(InImageBridgeChildThread());
   aClient->Release();
 }
 
 // static
 void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
 {
-  if (!IsCreated()) {
-    // TextureClient::Release should normally happen in the ImageBridgeChild
-    // thread because it usually generate some IPDL messages.
-    // However, if we take this branch it means that the ImageBridgeChild
-    // has already shut down, along with the TextureChild, which means no
-    // message will be sent and it is safe to run this code from any thread.
-    MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
-    aClient->Release();
-    return;
-  }
-
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction(&ReleaseTextureClientNow, aClient));
 }
 
 static void UpdateImageClientNow(ImageClient* aClient, ImageContainer* aContainer)
 {
   MOZ_ASSERT(aClient);
@@ -412,20 +363,16 @@ static void UpdateImageClientNow(ImageCl
   aClient->OnTransaction();
   sImageBridgeChildSingleton->EndTransaction();
 }
 
 //static
 void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
                                                  ImageContainer* aContainer)
 {
-  if (!IsCreated()) {
-    return;
-  }
-
   if (InImageBridgeChildThread()) {
     UpdateImageClientNow(aClient, aContainer);
     return;
   }
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction<
       void (*)(ImageClient*, ImageContainer*),
@@ -440,20 +387,16 @@ static void FlushAllImagesSync(ImageClie
   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   *aDone = true;
   aBarrier->NotifyAll();
 }
 
 //static
 void ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
 {
-  if (!IsCreated()) {
-    return;
-  }
-
   if (InImageBridgeChildThread()) {
     FlushAllImagesNow(aClient, aContainer, aExceptFront);
     return;
   }
 
   ReentrantMonitor barrier("CreateImageClient Lock");
   ReentrantMonitorAutoEnter autoMon(barrier);
   bool done = false;
@@ -468,30 +411,28 @@ void ImageBridgeChild::FlushAllImages(Im
     barrier.Wait();
   }
 }
 
 //static
 void ImageBridgeChild::FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
 {
   MOZ_ASSERT(aClient);
-  MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
   sImageBridgeChildSingleton->BeginTransaction();
   if (aContainer && !aExceptFront) {
     aContainer->ClearCurrentImage();
   }
   aClient->FlushAllImages(aExceptFront);
   aClient->OnTransaction();
   sImageBridgeChildSingleton->EndTransaction();
 }
 
 void
 ImageBridgeChild::BeginTransaction()
 {
-  MOZ_ASSERT(!mShuttingDown);
   MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
   mTxn->Begin();
 }
 
 class MOZ_STACK_CLASS AutoRemoveTextures
 {
 public:
   AutoRemoveTextures(ImageBridgeChild* aImageBridge)
@@ -503,17 +444,16 @@ public:
   }
 private:
   ImageBridgeChild* mImageBridge;
 };
 
 void
 ImageBridgeChild::EndTransaction()
 {
-  MOZ_ASSERT(!mShuttingDown);
   MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
 
   AutoEndTransaction _(mTxn);
   AutoRemoveTextures autoRemoveTextures(this);
 
   if (mTxn->IsEmpty()) {
     return;
   }
@@ -597,37 +537,19 @@ ImageBridgeChild::StartUpInChildProcess(
     NewRunnableFunction(ConnectImageBridgeInChildProcess,
                         aTransport, processHandle));
 
   return sImageBridgeChildSingleton;
 }
 
 void ImageBridgeChild::ShutDown()
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
+  NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
   if (ImageBridgeChild::IsCreated()) {
-    MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
-
-    ReentrantMonitor barrier("ImageBridgeDestroyTask lock");
-    ReentrantMonitorAutoEnter autoMon(barrier);
-
-    bool done = false;
-    sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
-                    NewRunnableFunction(&ImageBridgeShutdownStep1, &barrier, &done));
-    while (!done) {
-      barrier.Wait();
-    }
-
-    done = false;
-    sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
-                    NewRunnableFunction(&ImageBridgeShutdownStep2, &barrier, &done));
-    while (!done) {
-      barrier.Wait();
-    }
-
+    ImageBridgeChild::DestroyBridge();
     delete sImageBridgeChildThread;
     sImageBridgeChildThread = nullptr;
   }
 }
 
 bool ImageBridgeChild::StartUpOnThread(Thread* aThread)
 {
   NS_ABORT_IF_FALSE(aThread, "ImageBridge needs a thread.");
@@ -641,16 +563,45 @@ bool ImageBridgeChild::StartUpOnThread(T
       CompositorParent::CompositorLoop(), nullptr);
     sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton);
     return true;
   } else {
     return false;
   }
 }
 
+void ImageBridgeChild::DestroyBridge()
+{
+  if (!IsCreated()) {
+    return;
+  }
+  NS_ABORT_IF_FALSE(!InImageBridgeChildThread(),
+                    "This method must not be called in this thread.");
+  // ...because we are about to dispatch synchronous messages to the
+  // ImageBridgeChild thread.
+
+  ReentrantMonitor barrier("ImageBridgeDestroyTask lock");
+  ReentrantMonitorAutoEnter autoMon(barrier);
+
+  bool done = false;
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
+                  NewRunnableFunction(&StopImageBridgeSync, &barrier, &done));
+  while (!done) {
+    barrier.Wait();
+  }
+
+  done = false;
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
+                  NewRunnableFunction(&DeleteImageBridgeSync, &barrier, &done));
+  while (!done) {
+    barrier.Wait();
+  }
+
+}
+
 bool InImageBridgeChildThread()
 {
   return ImageBridgeChild::IsCreated() &&
     sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
 }
 
 MessageLoop * ImageBridgeChild::GetMessageLoop() const
 {
@@ -690,31 +641,29 @@ ImageBridgeChild::CreateImageClient(Comp
     barrier.Wait();
   }
   return result.forget();
 }
 
 TemporaryRef<ImageClient>
 ImageBridgeChild::CreateImageClientNow(CompositableType aType)
 {
-  MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
   RefPtr<ImageClient> client
     = ImageClient::CreateImageClient(aType, this, TextureFlags::NO_FLAGS);
   MOZ_ASSERT(client, "failed to create ImageClient");
   if (client) {
     client->Connect();
   }
   return client.forget();
 }
 
 PGrallocBufferChild*
 ImageBridgeChild::AllocPGrallocBufferChild(const IntSize&, const uint32_t&, const uint32_t&,
                                            MaybeMagicGrallocBufferHandle*)
 {
-  MOZ_ASSERT(!mShuttingDown);
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   return GrallocBufferActor::Create();
 #else
   NS_RUNTIMEABORT("No gralloc buffers for you");
   return nullptr;
 #endif
 }
 
@@ -730,30 +679,28 @@ ImageBridgeChild::DeallocPGrallocBufferC
 #endif
 }
 
 bool
 ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
                                    ipc::SharedMemory::SharedMemoryType aType,
                                    ipc::Shmem* aShmem)
 {
-  MOZ_ASSERT(!mShuttingDown);
   if (InImageBridgeChildThread()) {
     return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
   } else {
     return DispatchAllocShmemInternal(aSize, aType, aShmem, true); // true: unsafe
   }
 }
 
 bool
 ImageBridgeChild::AllocShmem(size_t aSize,
                              ipc::SharedMemory::SharedMemoryType aType,
                              ipc::Shmem* aShmem)
 {
-  MOZ_ASSERT(!mShuttingDown);
   if (InImageBridgeChildThread()) {
     return PImageBridgeChild::AllocShmem(aSize, aType, aShmem);
   } else {
     return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe
   }
 }
 
 // NewRunnableFunction accepts a limited number of parameters so we need a
@@ -883,17 +830,16 @@ ImageBridgeChild::AllocGrallocBuffer(con
 }
 
 void
 ImageBridgeChild::AllocGrallocBufferNow(const gfx::IntSize& aSize,
                                         uint32_t aFormat, uint32_t aUsage,
                                         MaybeMagicGrallocBufferHandle* aHandle,
                                         PGrallocBufferChild** aChild)
 {
-  MOZ_ASSERT(!mShuttingDown);
 #ifdef MOZ_WIDGET_GONK
   *aChild = SendPGrallocBufferConstructor(aSize,
                                           aFormat,
                                           aUsage,
                                           aHandle);
 #else
   NS_RUNTIMEABORT("not implemented");
   aChild = nullptr;
@@ -946,39 +892,36 @@ ImageBridgeChild::DeallocGrallocBuffer(P
     }
   }
 }
 
 PTextureChild*
 ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
                                      const TextureFlags&)
 {
-  MOZ_ASSERT(!mShuttingDown);
   return TextureClient::CreateIPDLActor();
 }
 
 bool
 ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
 {
   return TextureClient::DestroyIPDLActor(actor);
 }
 
 PTextureChild*
 ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
                                 TextureFlags aFlags)
 {
-  MOZ_ASSERT(!mShuttingDown);
   return SendPTextureConstructor(aSharedData, aFlags);
 }
 
 void
 ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                                 TextureClient* aTexture)
 {
-  MOZ_ASSERT(!mShuttingDown);
   if (aTexture->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
     mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
                                   nullptr, aTexture->GetIPDLActor()));
   } else {
     mTxn->AddNoSwapEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
                                         nullptr, aTexture->GetIPDLActor()));
   }
   // Hold texture until transaction complete.
@@ -992,17 +935,16 @@ static void RemoveTextureSync(TextureCli
   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   *aDone = true;
   aBarrier->NotifyAll();
 }
 
 void ImageBridgeChild::RemoveTexture(TextureClient* aTexture)
 {
   if (InImageBridgeChildThread()) {
-    MOZ_ASSERT(!mShuttingDown);
     aTexture->ForceRemove();
     return;
   }
 
   ReentrantMonitor barrier("RemoveTexture Lock");
   ReentrantMonitorAutoEnter autoMon(barrier);
   bool done = false;
 
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -126,16 +126,25 @@ public:
   static void ShutDown();
 
   /**
    * Creates the ImageBridgeChild manager protocol.
    */
   static bool StartUpOnThread(base::Thread* aThread);
 
   /**
+   * Destroys The ImageBridge protcol.
+   *
+   * The actual destruction happens synchronously on the ImageBridgeChild thread
+   * which means that if this function is called from another thread, the current
+   * thread will be paused until the destruction is done.
+   */
+  static void DestroyBridge();
+
+  /**
    * Returns true if the singleton has been created.
    *
    * Can be called from any thread.
    */
   static bool IsCreated();
 
   /**
    * returns the singleton instance.
@@ -300,32 +309,29 @@ public:
                                        TextureFlags aFlags) MOZ_OVERRIDE;
 
   virtual bool IsSameProcess() const MOZ_OVERRIDE;
 
   void AllocGrallocBufferNow(const gfx::IntSize& aSize,
                              uint32_t aFormat, uint32_t aUsage,
                              MaybeMagicGrallocBufferHandle* aHandle,
                              PGrallocBufferChild** aChild);
-  void MarkShutDown();
 protected:
   ImageBridgeChild();
   bool DispatchAllocShmemInternal(size_t aSize,
                                   SharedMemory::SharedMemoryType aType,
                                   Shmem* aShmem,
                                   bool aUnsafe);
 
   CompositableTransaction* mTxn;
 
   // ISurfaceAllocator
   virtual PGrallocBufferChild* AllocGrallocBuffer(const gfx::IntSize& aSize,
                                                   uint32_t aFormat, uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
 
   virtual void DeallocGrallocBuffer(PGrallocBufferChild* aChild) MOZ_OVERRIDE;
-
-  bool mShuttingDown;
 };
 
 } // layers
 } // mozilla
 
 #endif
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -134,38 +134,31 @@ ImageBridgeParent::Create(Transport* aTr
   nsRefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport);
   bridge->mSelfRef = bridge;
   loop->PostTask(FROM_HERE,
                  NewRunnableFunction(ConnectImageBridgeInParentProcess,
                                      bridge.get(), aTransport, processHandle));
   return bridge.get();
 }
 
-bool ImageBridgeParent::RecvWillStop()
+bool ImageBridgeParent::RecvStop()
 {
   // If there is any texture still alive we have to force it to deallocate the
   // device data (GL textures, etc.) now because shortly after SenStop() returns
   // on the child side the widget will be destroyed along with it's associated
   // GL context.
   InfallibleTArray<PTextureParent*> textures;
   ManagedPTextureParent(textures);
   for (unsigned int i = 0; i < textures.Length(); ++i) {
     RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]);
     tex->DeallocateDeviceData();
   }
   return true;
 }
 
-bool ImageBridgeParent::RecvStop()
-{
-  // Nothing to do. This message just serves as synchronization between the
-  // child and parent threads during shutdown.
-  return true;
-}
-
 static  uint64_t GenImageContainerID() {
   static uint64_t sNextImageID = 1;
 
   ++sNextImageID;
   return sNextImageID;
 }
 
 PGrallocBufferParent*
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -65,20 +65,17 @@ public:
   PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo,
                                                 uint64_t*) MOZ_OVERRIDE;
   bool DeallocPCompositableParent(PCompositableParent* aActor) MOZ_OVERRIDE;
 
   virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
                                               const TextureFlags& aFlags) MOZ_OVERRIDE;
   virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
 
-  // Shutdown step 1
-  virtual bool RecvWillStop() MOZ_OVERRIDE;
-  // Shutdown step 2
-  virtual bool RecvStop() MOZ_OVERRIDE;
+  bool RecvStop() MOZ_OVERRIDE;
 
   MessageLoop * GetMessageLoop();
 
 
   // ISurfaceAllocator
 
   bool AllocShmem(size_t aSize,
                   ipc::SharedMemory::SharedMemoryType aType,
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -37,25 +37,23 @@ parent:
   // Allocates a gralloc buffer that may not suitable to use with
   // gfxImageSurface but allows hardware decoder to write to the
   // buffer directly. The format is a enum defined in
   // system/graphics.h and the usage is the GraphicBuffer usage
   // flag. See GraphicBuffer.h and gralloc.h.
   sync PGrallocBuffer(IntSize size, uint32_t format, uint32_t usage)
     returns (MaybeMagicGrallocBufferHandle handle);
 
-  // First step of the destruction sequence. This puts ImageBridge
-  // in a state in which it can't send asynchronous messages
-  // so as to not race with the upcomming Stop message and destruction.
-  // In the child side, the Stop message is not sent right after WillStop,
-  // it is scheduled in the ImageBridgeChild's message queue in order to ensure
-  // that all of the messages from the parent side have been received and processed
-  // before sending Stop, and that after Stop returns, there is no message in
-  // flight on any side and we can safely destroy the channel and threads.
-  sync WillStop();
+  // First step of the destruction sequence. This puts all the ImageContainerParents
+  // in a state in which they can't send asynchronous messages to their child
+  // counterpart so as to not race with the upcomming __delete__ message.
+  // In the child side, the __delete__ messages are not sent right after Stop,
+  // they are scheduled in the ImageBridgeChild's message queue in order to ensure
+  // that all the messages from the parent side have been received and processed
+  // before sending __delete__.
   sync Stop();
 
   sync PCompositable(TextureInfo aInfo) returns (uint64_t id);
   async PTexture(SurfaceDescriptor aSharedData, TextureFlags aTextureFlags);
 };
 
 
 } // namespace
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -488,16 +488,22 @@ gfxPlatform::Shutdown()
     // most platforms.  Windows is a "special snowflake", though, and has three
     // context providers available, so we have to shut all of them down.
     // We should only support the default GL provider on Windows; then, this
     // could go away. Unfortunately, we currently support WGL (the default) for
     // WebGL on Optimus.
     mozilla::gl::GLContextProviderEGL::Shutdown();
 #endif
 
+    // This will block this thread untill the ImageBridge protocol is completely
+    // deleted.
+    ImageBridgeChild::ShutDown();
+
+    CompositorParent::ShutDown();
+
     delete gGfxPlatformPrefsLock;
 
     gfxPrefs::DestroySingleton();
     gfxFont::DestroySingletons();
 
     delete gPlatform;
     gPlatform = nullptr;
 }
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -784,21 +784,16 @@ ShutdownXPCOM(nsIServiceManager* servMgr
             if (NS_SUCCEEDED(rv))
             {
                 (void) observerService->
                     NotifyObservers(mgr, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
                                     nullptr);
             }
         }
 
-        // This must happen after the shutdown of media and widgets, which
-        // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
-        mozilla::layers::ImageBridgeChild::ShutDown();
-        mozilla::layers::CompositorParent::ShutDown();
-
         NS_ProcessPendingEvents(thread);
         mozilla::scache::StartupCache::DeleteSingleton();
         if (observerService)
             (void) observerService->
                 NotifyObservers(nullptr, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID,
                                 nullptr);
 
         gXPCOMThreadsShutDown = true;