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 200316 a6864d25a859d0918bd52e12f409d8247edd9d35
parent 200315 b850412044d73daf27778fe93b28d6fe2b92d5af
child 200317 34887cdb561622ec80c4d80e249a87224be9b553
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs924622
milestone32.0a1
backs out74ef5120ae2f590d8b766806025610f200ca3c8a
d26dfd37031a884671ac9ce57d6cc62d8463be3c
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
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;