Fix APZCs leaking when a compositor shuts down. (bug 1147681 part 2, r=kats)
authorDavid Anderson <danderson@mozilla.com>
Thu, 26 Mar 2015 14:24:37 -0700
changeset 235909 6f42f8ee82468d18acd65e0c2b5bf6c040696224
parent 235908 c2179c027c28922befd5617fdb5c5728cc387b10
child 235910 4f8bbef857155fbee1d064e014b22dd72512b389
push id57543
push userdanderson@mozilla.com
push dateThu, 26 Mar 2015 21:25:02 +0000
treeherdermozilla-inbound@6f42f8ee8246 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1147681
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
Fix APZCs leaking when a compositor shuts down. (bug 1147681 part 2, r=kats)
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/InputQueue.cpp
gfx/layers/apz/src/InputQueue.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1055,16 +1055,22 @@ APZCTreeManager::CancelAnimation(const S
   if (apzc) {
     apzc->CancelAnimation();
   }
 }
 
 void
 APZCTreeManager::ClearTree()
 {
+  // Ensure that no references to APZCs are alive in any lingering input
+  // blocks. This breaks cycles from InputBlockState::mTargetApzc back to
+  // the InputQueue.
+  APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
+    mInputQueue.get(), &InputQueue::Clear));
+
   MonitorAutoLock lock(mTreeLock);
 
   // This can be done as part of a tree walk but it's easier to
   // just re-use the Collect method that we need in other places.
   // If this is too slow feel free to change it to a recursive walk.
   nsTArray<nsRefPtr<HitTestingTreeNode>> nodesToDestroy;
   Collect(mRootNode, &nodesToDestroy);
   for (size_t i = 0; i < nodesToDestroy.Length(); i++) {
--- a/gfx/layers/apz/src/InputQueue.cpp
+++ b/gfx/layers/apz/src/InputQueue.cpp
@@ -455,10 +455,18 @@ InputQueue::ProcessInputBlocks() {
 
     // If we get here, we know there are more touch blocks in the queue after
     // |curBlock|, so we can remove |curBlock| and try to process the next one.
     INPQ_LOG("discarding processed %s block %p\n", curBlock->Type(), curBlock);
     mInputBlockQueue.RemoveElementAt(0);
   } while (!mInputBlockQueue.IsEmpty());
 }
 
+void
+InputQueue::Clear()
+{
+  APZThreadUtils::AssertOnControllerThread();
+
+  mInputBlockQueue.Clear();
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/apz/src/InputQueue.h
+++ b/gfx/layers/apz/src/InputQueue.h
@@ -95,16 +95,20 @@ public:
    * handling.
    */
   bool HasReadyTouchBlock() const;
   /**
    * If there is a wheel transaction, returns the WheelBlockState representing
    * the transaction. Otherwise, returns null.
    */
   WheelBlockState* GetCurrentWheelTransaction() const;
+  /**
+   * Remove all input blocks from the input queue.
+   */
+  void Clear();
 
 private:
   ~InputQueue();
 
   TouchBlockState* StartNewTouchBlock(const nsRefPtr<AsyncPanZoomController>& aTarget,
                                       bool aTargetConfirmed,
                                       bool aCopyPropertiesFromCurrent);