Bug 1125848 - Prevent PCompositorChild messages to be sent after the actor started shutting down. r=sotaro, a=lmandel
authorNicolas Silva <nsilva@mozilla.com>
Thu, 05 Mar 2015 19:03:16 +0100
changeset 250270 a082a6e1cd99
parent 250267 e4f2ee87f064
child 250271 dc8372b4cfd6
push id4531
push usernsilva@mozilla.com
push date2015-03-06 13:47 +0000
treeherdermozilla-beta@a082a6e1cd99 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro, lmandel
bugs1125848
milestone37.0
Bug 1125848 - Prevent PCompositorChild messages to be sent after the actor started shutting down. r=sotaro, a=lmandel
gfx/layers/ipc/CompositorChild.cpp
gfx/layers/ipc/CompositorChild.h
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -31,16 +31,17 @@ namespace mozilla {
 namespace layers {
 
 /*static*/ CompositorChild* CompositorChild::sCompositor;
 
 Atomic<int32_t> CompositableForwarder::sSerialCounter(0);
 
 CompositorChild::CompositorChild(ClientLayerManager *aLayerManager)
   : mLayerManager(aLayerManager)
+  , mCanSend(true)
 {
 }
 
 CompositorChild::~CompositorChild()
 {
 }
 
 void
@@ -50,16 +51,17 @@ CompositorChild::Destroy()
   mLayerManager = nullptr;
   // start from the end of the array because Destroy() can cause the
   // LayerTransactionChild to be removed from the array.
   for (int i = ManagedPLayerTransactionChild().Length() - 1; i >= 0; --i) {
     RefPtr<LayerTransactionChild> layers =
       static_cast<LayerTransactionChild*>(ManagedPLayerTransactionChild()[i]);
     layers->Destroy();
   }
+  MOZ_ASSERT(!mCanSend);
   SendStop();
 }
 
 bool
 CompositorChild::LookupCompositorFrameMetrics(const FrameMetrics::ViewID aId,
                                               FrameMetrics& aFrame)
 {
   SharedFrameMetricsData* data = mFrameMetricsTable.Get(aId);
@@ -108,16 +110,17 @@ CompositorChild::Get()
 }
 
 PLayerTransactionChild*
 CompositorChild::AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBackendHints,
                                              const uint64_t& aId,
                                              TextureFactoryIdentifier*,
                                              bool*)
 {
+  MOZ_ASSERT(mCanSend);
   LayerTransactionChild* c = new LayerTransactionChild();
   c->AddIPDLReference();
   return c;
 }
 
 bool
 CompositorChild::DeallocPLayerTransactionChild(PLayerTransactionChild* actor)
 {
@@ -315,11 +318,131 @@ CompositorChild::CancelNotifyAfterRemote
   }
   TabChildBase* tabChildBase = static_cast<TabChildBase*>(iTabChildBase.get());
   TabChild* tabChild = static_cast<TabChild*>(tabChildBase);
   if (tabChild == aTabChild) {
     mWeakTabChild = nullptr;
   }
 }
 
+bool
+CompositorChild::SendWillStop()
+{
+  MOZ_ASSERT(mCanSend);
+  // From now on the only two messages we can send are WillStop and Stop.
+  mCanSend = false;
+  return PCompositorChild::SendWillStop();
+}
+
+bool
+CompositorChild::SendPause()
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendPause();
+}
+
+bool
+CompositorChild::SendResume()
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendResume();
+}
+
+bool
+CompositorChild::SendNotifyChildCreated(const uint64_t& id)
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendNotifyChildCreated(id);
+}
+
+bool
+CompositorChild::SendAdoptChild(const uint64_t& id)
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendAdoptChild(id);
+}
+
+bool
+CompositorChild::SendMakeSnapshot(const SurfaceDescriptor& inSnapshot, const nsIntRect& dirtyRect)
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendMakeSnapshot(inSnapshot, dirtyRect);
+}
+
+bool
+CompositorChild::SendFlushRendering()
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendFlushRendering();
+}
+
+bool
+CompositorChild::SendGetTileSize(int32_t* tileWidth, int32_t* tileHeight)
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendGetTileSize(tileWidth, tileHeight);
+}
+
+bool
+CompositorChild::SendStartFrameTimeRecording(const int32_t& bufferSize, uint32_t* startIndex)
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendStartFrameTimeRecording(bufferSize, startIndex);
+}
+
+bool
+CompositorChild::SendStopFrameTimeRecording(const uint32_t& startIndex, nsTArray<float>* intervals)
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendStopFrameTimeRecording(startIndex, intervals);
+}
+
+bool
+CompositorChild::SendNotifyRegionInvalidated(const nsIntRegion& region)
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendNotifyRegionInvalidated(region);
+}
+
+bool
+CompositorChild::SendRequestNotifyAfterRemotePaint()
+{
+  MOZ_ASSERT(mCanSend);
+  if (!mCanSend) {
+    return true;
+  }
+  return PCompositorChild::SendRequestNotifyAfterRemotePaint();
+}
+
+
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/ipc/CompositorChild.h
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -77,16 +77,35 @@ public:
    * @param tabChild The object to bounce the note to.  Non-NULL.
    */
   void RequestNotifyAfterRemotePaint(TabChild* aTabChild);
 
   void CancelNotifyAfterRemotePaint(TabChild* aTabChild);
 
   static void ShutDown();
 
+  // Beware that these methods don't override their super-class equivalent (which
+  // are not virtual), they just overload them.
+  // All of these Send* methods just add a sanity check (that it is not too late
+  // send a message) and forward the call to the super-class's equivalent method.
+  // This means that it is correct to call directly the super-class methods, but
+  // you won't get the extra safety provided here.
+  bool SendWillStop();
+  bool SendPause();
+  bool SendResume();
+  bool SendNotifyChildCreated(const uint64_t& id);
+  bool SendAdoptChild(const uint64_t& id);
+  bool SendMakeSnapshot(const SurfaceDescriptor& inSnapshot, const nsIntRect& dirtyRect);
+  bool SendFlushRendering();
+  bool SendGetTileSize(int32_t* tileWidth, int32_t* tileHeight);
+  bool SendStartFrameTimeRecording(const int32_t& bufferSize, uint32_t* startIndex);
+  bool SendStopFrameTimeRecording(const uint32_t& startIndex, nsTArray<float>* intervals);
+  bool SendNotifyRegionInvalidated(const nsIntRegion& region);
+  bool SendRequestNotifyAfterRemotePaint();
+
 private:
   // Private destructor, to discourage deletion outside of Release():
   virtual ~CompositorChild();
 
   virtual PLayerTransactionChild*
     AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBackendHints,
                                 const uint64_t& aId,
                                 TextureFactoryIdentifier* aTextureFactoryIdentifier,
@@ -143,14 +162,17 @@ private:
   // Weakly hold the TabChild that made a request to be alerted when
   // the transaction has been received.
   nsWeakPtr mWeakTabChild;      // type is TabChild
 
   DISALLOW_EVIL_CONSTRUCTORS(CompositorChild);
 
   // When we receive overfill numbers, notify these client layer managers
   nsAutoTArray<ClientLayerManager*,0> mOverfillObservers;
+
+  // True until the beginning of the two-step shutdown sequence of this actor.
+  bool mCanSend;
 };
 
 } // layers
 } // mozilla
 
 #endif // mozilla_layers_CompositorChild_h