Bug 1125848 - Prevent PCompositorChild messages to be sent after the actor started shutting down. r=sotaro
authorNicolas Silva <nsilva@mozilla.com>
Thu, 05 Mar 2015 19:03:16 +0100
changeset 260906 1c85afc8c1894972fbca0c9043279ecbdaad2509
parent 260905 4bcedf1c976cc81ba5da31ff13dd0bf8771d208f
child 260907 09462adb077d0a0f1a1cf6a4e8f1815c7fb9c39d
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs1125848
milestone39.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 1125848 - Prevent PCompositorChild messages to be sent after the actor started shutting down. r=sotaro
gfx/layers/ipc/CompositorChild.cpp
gfx/layers/ipc/CompositorChild.h
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -35,16 +35,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
@@ -54,16 +55,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);
@@ -113,16 +115,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)
 {
@@ -302,16 +305,17 @@ CompositorChild::AddOverfillObserver(Cli
 {
   MOZ_ASSERT(aLayerManager);
   mOverfillObservers.AppendElement(aLayerManager);
 }
 
 void
 CompositorChild::ActorDestroy(ActorDestroyReason aWhy)
 {
+  MOZ_ASSERT(!mCanSend);
   MOZ_ASSERT(sCompositor == this);
 
 #ifdef MOZ_B2G
   // Due to poor lifetime management of gralloc (and possibly shmems) we will
   // crash at some point in the future when we get destroyed due to abnormal
   // shutdown. Its better just to crash here. On desktop though, we have a chance
   // of recovering.
   if (aWhy == AbnormalShutdown) {
@@ -446,11 +450,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
@@ -88,16 +88,35 @@ public:
    * When we get that message, we bounce it to the TabParent via
    * the TabChild
    * @param tabChild The object to bounce the note to.  Non-NULL.
    */
   void RequestNotifyAfterRemotePaint(TabChild* aTabChild);
 
   void CancelNotifyAfterRemotePaint(TabChild* aTabChild);
 
+  // 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,
@@ -154,14 +173,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