Crash under DisplayRefreshMonitorManager::displayWasUpdated()
https://bugs.webkit.org/show_bug.cgi?id=199808
<rdar://problem/53070144>

Reviewed by Geoffrey Garen.

Copy m_monitors before iterating over it because the calling displayLinkFired() on the
monitor may end up calling DisplayRefreshMonitorManager::displayDidRefresh() synchronously,
which removes the monitor from m_monitors.

* platform/graphics/DisplayRefreshMonitorManager.cpp:
(WebCore::DisplayRefreshMonitorManager::displayWasUpdated):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@247459 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 8cc638e..39fe382 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,18 @@
+2019-07-15  Chris Dumez  <cdumez@apple.com>
+
+        Crash under DisplayRefreshMonitorManager::displayWasUpdated()
+        https://bugs.webkit.org/show_bug.cgi?id=199808
+        <rdar://problem/53070144>
+
+        Reviewed by Geoffrey Garen.
+
+        Copy m_monitors before iterating over it because the calling displayLinkFired() on the
+        monitor may end up calling DisplayRefreshMonitorManager::displayDidRefresh() synchronously,
+        which removes the monitor from m_monitors.
+
+        * platform/graphics/DisplayRefreshMonitorManager.cpp:
+        (WebCore::DisplayRefreshMonitorManager::displayWasUpdated):
+
 2019-07-15  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Improve wasm wpt test results by fixing miscellaneous issues
diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp b/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp
index 4d3cd69..699f85d 100644
--- a/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp
+++ b/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp
@@ -128,8 +128,10 @@
 
 void DisplayRefreshMonitorManager::displayWasUpdated(PlatformDisplayID displayID)
 {
-    for (const auto& monitorWrapper : m_monitors) {
-        auto& monitor = monitorWrapper.monitor;
+    Vector<RefPtr<DisplayRefreshMonitor>> monitors = WTF::map(m_monitors, [](auto& monitorWrapper) {
+        return monitorWrapper.monitor;
+    });
+    for (auto& monitor : monitors) {
         if (displayID == monitor->displayID() && monitor->hasRequestedRefreshCallback())
             monitor->displayLinkFired();
     }