From dd9027868296e913f7d0bc9a4791c7beb5874742 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Fri, 25 Apr 2014 13:38:09 -0400 Subject: [PATCH] Bug 1000633 - Avoid APZ data race in accessing mAnimation. r=kats --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 16 ++++++++++++---- gfx/layers/apz/src/AsyncPanZoomController.h | 12 ++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index c09e5aee317..346f2255e9b 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1602,6 +1602,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa // smooth. If an animation frame is requested, it is the compositor's // responsibility to schedule a composite. bool requestAnimationFrame = false; + Vector deferredTasks; { ReentrantMonitorAutoEnter lock(mMonitor); @@ -1616,12 +1617,19 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa ParentLayerSize(mFrameMetrics.mCompositionBounds.Size()) / mFrameMetrics.GetZoomToParent())); mCurrentAsyncScrollOffset = mFrameMetrics.GetScrollOffset(); + + // Get any deferred tasks queued up by mAnimation's Sample() (called by + // UpdateAnimation()). This needs to be done here since mAnimation can + // be destroyed by another thread when we release the monitor, but + // the tasks need to be executed after we release the monitor since they + // are allowed to call APZCTreeManager methods which can grab the tree lock. + if (mAnimation) { + deferredTasks = mAnimation->TakeDeferredTasks(); + } } - // Execute tasks queued up by mAnimation's Sample() (called by - // UpdateAnimation()) for execution after mMonitor has been released. - if (mAnimation) { - mAnimation->ExecuteDeferredTasks(); + for (uint32_t i = 0; i < deferredTasks.length(); ++i) { + deferredTasks[i]->Run(); } // Cancel the mAsyncScrollTimeoutTask because we will fire a diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 3c67ba157da..3bae19f1531 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -948,14 +948,14 @@ public: const TimeDuration& aDelta) = 0; /** - * Execute the tasks in |mDeferredTasks| in order. See |mDeferredTasks| + * Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks| * for more information. + * Clears |mDeferredTasks|. */ - void ExecuteDeferredTasks() { - for (uint32_t i = 0; i < mDeferredTasks.length(); ++i) { - mDeferredTasks[i]->Run(); - } - mDeferredTasks.clear(); + Vector TakeDeferredTasks() { + Vector result; + mDeferredTasks.swap(result); + return result; } /**