diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp index 0dbbfa647595..abf640c679c6 100644 --- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -584,7 +584,15 @@ APZCTreeManager::ClearTree() void APZCTreeManager::HandleOverscroll(AsyncPanZoomController* aChild, ScreenPoint aStartPoint, ScreenPoint aEndPoint) { - AsyncPanZoomController* parent = aChild->GetParent(); + nsRefPtr parent; + { + // The tree lock needs to be held while navigating from an apzc to its + // parent. We don't hold it any longer though because GetInputTransforms() + // does its own locking, and AttemptScroll() can call HandleOverscroll() + // recursively. + MonitorAutoLock lock(mTreeLock); + parent = aChild->GetParent(); + } if (parent == nullptr) return; @@ -597,7 +605,7 @@ APZCTreeManager::HandleOverscroll(AsyncPanZoomController* aChild, ScreenPoint aS ApplyTransform(&aEndPoint, transformToApzc.Inverse()); // Convert start and end points to parent's transformed screen coordinates. - GetInputTransforms(parent, transformToApzc, transformToGecko); + GetInputTransforms(parent.get(), transformToApzc, transformToGecko); ApplyTransform(&aStartPoint, transformToApzc); ApplyTransform(&aEndPoint, transformToApzc); diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 732df2b4159b..614fcf74ac40 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -862,8 +862,14 @@ void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint, } if (fabs(overscroll.x) > EPSILON || fabs(overscroll.y) > EPSILON) { - // "+ overscroll" rather than "- overscroll" for the same reason as above. - mTreeManager->HandleOverscroll(this, aEndPoint + overscroll, aEndPoint); + // Make a local copy of the tree manager pointer and check if it's not + // null before calling HandleOverscroll(). This is necessary because + // Destroy(), which nulls out mTreeManager, could be called concurrently. + APZCTreeManager* treeManagerLocal = mTreeManager; + if (treeManagerLocal) { + // "+ overscroll" rather than "- overscroll" for the same reason as above. + treeManagerLocal->HandleOverscroll(this, aEndPoint + overscroll, aEndPoint); + } } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 69b648b05920..bb39c39e3da5 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -13,6 +13,7 @@ #include "mozilla/Monitor.h" #include "mozilla/ReentrantMonitor.h" #include "mozilla/RefPtr.h" +#include "mozilla/Atomics.h" #include "InputData.h" #include "Axis.h" #include "TaskThrottler.h" @@ -648,7 +649,7 @@ private: // live on the main thread, we can't use the cycle collector with them. // The APZCTreeManager owns the lifetime of the APZCs, so nulling this // pointer out in Destroy() will prevent accessing deleted memory. - APZCTreeManager* mTreeManager; + Atomic mTreeManager; nsRefPtr mLastChild; nsRefPtr mPrevSibling;