Title: [247273] trunk/Source/WebCore
Revision
247273
Author
cdu...@apple.com
Date
2019-07-09 13:03:08 -0700 (Tue, 09 Jul 2019)

Log Message

Fix non thread-safe use of WeakPtr in DisplayRefreshMonitorMac::displayLinkFired()
https://bugs.webkit.org/show_bug.cgi?id=199626

Reviewed by Ryosuke Niwa.

Fix non thread-safe use of WeakPtr in DisplayRefreshMonitorMac::displayLinkFired().
DisplayRefreshMonitorMac gets constructed / destroyed on the main thread, it is
not thread-safe to call makeWeakPtr() on a DisplayRefreshMonitorMac object like it
was done before.

To address the issue, mark the object as ThreadSafeRefCounted and ref the object
in the lambda instead.

* platform/graphics/DisplayRefreshMonitor.h:
(WebCore::DisplayRefreshMonitor::stop):
* platform/graphics/DisplayRefreshMonitorManager.cpp:
(WebCore::DisplayRefreshMonitorManager::unregisterClient):
* platform/graphics/mac/DisplayRefreshMonitorMac.cpp:
(WebCore::DisplayRefreshMonitorMac::~DisplayRefreshMonitorMac):
(WebCore::DisplayRefreshMonitorMac::stop):
(WebCore::DisplayRefreshMonitorMac::displayLinkFired):
* platform/graphics/mac/DisplayRefreshMonitorMac.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (247272 => 247273)


--- trunk/Source/WebCore/ChangeLog	2019-07-09 19:56:24 UTC (rev 247272)
+++ trunk/Source/WebCore/ChangeLog	2019-07-09 20:03:08 UTC (rev 247273)
@@ -1,3 +1,28 @@
+2019-07-09  Chris Dumez  <cdu...@apple.com>
+
+        Fix non thread-safe use of WeakPtr in DisplayRefreshMonitorMac::displayLinkFired()
+        https://bugs.webkit.org/show_bug.cgi?id=199626
+
+        Reviewed by Ryosuke Niwa.
+
+        Fix non thread-safe use of WeakPtr in DisplayRefreshMonitorMac::displayLinkFired().
+        DisplayRefreshMonitorMac gets constructed / destroyed on the main thread, it is
+        not thread-safe to call makeWeakPtr() on a DisplayRefreshMonitorMac object like it
+        was done before.
+
+        To address the issue, mark the object as ThreadSafeRefCounted and ref the object
+        in the lambda instead.
+
+        * platform/graphics/DisplayRefreshMonitor.h:
+        (WebCore::DisplayRefreshMonitor::stop):
+        * platform/graphics/DisplayRefreshMonitorManager.cpp:
+        (WebCore::DisplayRefreshMonitorManager::unregisterClient):
+        * platform/graphics/mac/DisplayRefreshMonitorMac.cpp:
+        (WebCore::DisplayRefreshMonitorMac::~DisplayRefreshMonitorMac):
+        (WebCore::DisplayRefreshMonitorMac::stop):
+        (WebCore::DisplayRefreshMonitorMac::displayLinkFired):
+        * platform/graphics/mac/DisplayRefreshMonitorMac.h:
+
 2019-07-09  Sihui Liu  <sihui_...@apple.com>
 
         Only allow fetching and removing session credentials from WebsiteDataStore

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h (247272 => 247273)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2019-07-09 19:56:24 UTC (rev 247272)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2019-07-09 20:03:08 UTC (rev 247273)
@@ -30,7 +30,7 @@
 #include "PlatformScreen.h"
 #include <wtf/HashSet.h>
 #include <wtf/Lock.h>
-#include <wtf/RefCounted.h>
+#include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -38,7 +38,7 @@
 class DisplayAnimationClient;
 class DisplayRefreshMonitorClient;
 
-class DisplayRefreshMonitor : public RefCounted<DisplayRefreshMonitor> {
+class DisplayRefreshMonitor : public ThreadSafeRefCounted<DisplayRefreshMonitor> {
 public:
     static RefPtr<DisplayRefreshMonitor> create(DisplayRefreshMonitorClient&);
     WEBCORE_EXPORT virtual ~DisplayRefreshMonitor();
@@ -48,6 +48,9 @@
     // Return true if callback request was scheduled, false if it couldn't be
     // (e.g., hardware refresh is not available)
     virtual bool requestRefreshCallback() = 0;
+
+    virtual void stop() { }
+
     void windowScreenDidChange(PlatformDisplayID);
     
     bool hasClients() const { return m_clients.size(); }

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp (247272 => 247273)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2019-07-09 19:56:24 UTC (rev 247272)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2019-07-09 20:03:08 UTC (rev 247273)
@@ -45,7 +45,8 @@
 DisplayRefreshMonitor* DisplayRefreshMonitorManager::createMonitorForClient(DisplayRefreshMonitorClient& client)
 {
     PlatformDisplayID clientDisplayID = client.displayID();
-    for (const RefPtr<DisplayRefreshMonitor>& monitor : m_monitors) {
+    for (auto& monitorWrapper : m_monitors) {
+        auto& monitor = monitorWrapper.monitor;
         if (monitor->displayID() != clientDisplayID)
             continue;
         monitor->addClient(client);
@@ -59,7 +60,7 @@
     LOG(RequestAnimationFrame, "DisplayRefreshMonitorManager::createMonitorForClient() - created monitor %p", monitor.get());
     monitor->addClient(client);
     DisplayRefreshMonitor* result = monitor.get();
-    m_monitors.append(WTFMove(monitor));
+    m_monitors.append({ WTFMove(monitor) });
     return result;
 }
 
@@ -78,7 +79,7 @@
 
     PlatformDisplayID clientDisplayID = client.displayID();
     for (size_t i = 0; i < m_monitors.size(); ++i) {
-        RefPtr<DisplayRefreshMonitor> monitor = m_monitors[i];
+        RefPtr<DisplayRefreshMonitor> monitor = m_monitors[i].monitor;
         if (monitor->displayID() != clientDisplayID)
             continue;
         if (monitor->removeClient(client)) {
@@ -108,7 +109,7 @@
         return;
     LOG(RequestAnimationFrame, "DisplayRefreshMonitorManager::displayDidRefresh() - destroying monitor %p", &monitor);
 
-    size_t monitorIndex = m_monitors.find(&monitor);
+    size_t monitorIndex = m_monitors.findMatching([&](auto& monitorWrapper) { return monitorWrapper.monitor == &monitor; });
     if (monitorIndex != notFound)
         m_monitors.remove(monitorIndex);
 }
@@ -127,7 +128,8 @@
 
 void DisplayRefreshMonitorManager::displayWasUpdated(PlatformDisplayID displayID)
 {
-    for (const auto& monitor : m_monitors) {
+    for (const auto& monitorWrapper : m_monitors) {
+        auto& monitor = monitorWrapper.monitor;
         if (displayID == monitor->displayID() && monitor->hasRequestedRefreshCallback())
             monitor->displayLinkFired();
     }

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h (247272 => 247273)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2019-07-09 19:56:24 UTC (rev 247272)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2019-07-09 20:03:08 UTC (rev 247273)
@@ -57,7 +57,18 @@
 
     DisplayRefreshMonitor* createMonitorForClient(DisplayRefreshMonitorClient&);
 
-    Vector<RefPtr<DisplayRefreshMonitor>> m_monitors;
+    struct DisplayRefreshMonitorWrapper {
+        DisplayRefreshMonitorWrapper(DisplayRefreshMonitorWrapper&&) = default;
+        ~DisplayRefreshMonitorWrapper()
+        {
+            if (monitor)
+                monitor->stop();
+        }
+
+        RefPtr<DisplayRefreshMonitor> monitor;
+    };
+
+    Vector<DisplayRefreshMonitorWrapper> m_monitors;
 };
 
 }

Modified: trunk/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp (247272 => 247273)


--- trunk/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp	2019-07-09 19:56:24 UTC (rev 247272)
+++ trunk/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp	2019-07-09 20:03:08 UTC (rev 247273)
@@ -40,13 +40,19 @@
 
 DisplayRefreshMonitorMac::~DisplayRefreshMonitorMac()
 {
-    if (m_displayLink) {
-        CVDisplayLinkStop(m_displayLink);
-        CVDisplayLinkRelease(m_displayLink);
-        m_displayLink = nullptr;
-    }
+    ASSERT(!m_displayLink);
 }
 
+void DisplayRefreshMonitorMac::stop()
+{
+    if (!m_displayLink)
+        return;
+
+    CVDisplayLinkStop(m_displayLink);
+    CVDisplayLinkRelease(m_displayLink);
+    m_displayLink = nullptr;
+}
+
 static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* data)
 {
     DisplayRefreshMonitorMac* monitor = static_cast<DisplayRefreshMonitorMac*>(data);
@@ -89,9 +95,9 @@
 
     setIsPreviousFrameDone(false);
 
-    RunLoop::main().dispatch([weakPtr = makeWeakPtr(*this)] {
-        if (auto* monitor = weakPtr.get())
-            handleDisplayRefreshedNotificationOnMainThread(monitor);
+    RunLoop::main().dispatch([this, protectedThis = makeRef(*this)] {
+        if (m_displayLink)
+            handleDisplayRefreshedNotificationOnMainThread(this);
     });
 }
 

Modified: trunk/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.h (247272 => 247273)


--- trunk/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.h	2019-07-09 19:56:24 UTC (rev 247272)
+++ trunk/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.h	2019-07-09 20:03:08 UTC (rev 247273)
@@ -34,7 +34,7 @@
 
 namespace WebCore {
 
-class DisplayRefreshMonitorMac : public DisplayRefreshMonitor, public CanMakeWeakPtr<DisplayRefreshMonitorMac> {
+class DisplayRefreshMonitorMac : public DisplayRefreshMonitor {
 public:
     static Ref<DisplayRefreshMonitorMac> create(PlatformDisplayID displayID)
     {
@@ -45,6 +45,7 @@
 
     void displayLinkFired() override;
     bool requestRefreshCallback() override;
+    void stop() override;
 
 private:
     explicit DisplayRefreshMonitorMac(PlatformDisplayID);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to