Fix crash in ProcessLauncher socket monitor callback
authorMichael Catanzaro <mcatanzaro@redhat.com>
Thu, 17 Oct 2024 14:52:26 +0000 (16:52 +0200)
committerAlberto Garcia <berto@igalia.com>
Thu, 17 Oct 2024 14:52:26 +0000 (16:52 +0200)
Bug: https://bugs.webkit.org/show_bug.cgi?id=281495

===================================================================

Gbp-Pq: Name socket-monitor-crash.patch

Source/WTF/wtf/glib/GSocketMonitor.cpp
Source/WTF/wtf/glib/GSocketMonitor.h

index c88ea9f91ca49ab2861bb4da44bd96529969b236..f3e31efb505306fcc98580dd5b53f58b6d3d2473 100644 (file)
@@ -33,6 +33,7 @@ namespace WTF {
 
 GSocketMonitor::~GSocketMonitor()
 {
+    RELEASE_ASSERT(!m_isExecutingCallback);
     stop();
 }
 
@@ -40,7 +41,17 @@ gboolean GSocketMonitor::socketSourceCallback(GSocket*, GIOCondition condition,
 {
     if (g_cancellable_is_cancelled(monitor->m_cancellable.get()))
         return G_SOURCE_REMOVE;
-    return monitor->m_callback(condition);
+
+    monitor->m_isExecutingCallback = true;
+    gboolean result = monitor->m_callback(condition);
+    monitor->m_isExecutingCallback = false;
+
+    if (monitor->m_shouldDestroyCallback) {
+        monitor->m_callback = nullptr;
+        monitor->m_shouldDestroyCallback = false;
+    }
+
+    return result;
 }
 
 void GSocketMonitor::start(GSocket* socket, GIOCondition condition, RunLoop& runLoop, Function<gboolean(GIOCondition)>&& callback)
@@ -65,7 +76,13 @@ void GSocketMonitor::stop()
     m_cancellable = nullptr;
     g_source_destroy(m_source.get());
     m_source = nullptr;
-    m_callback = nullptr;
+
+    // It's normal to stop the socket monitor from inside its callback.
+    // Don't destroy the callback while it's still executing.
+    if (m_isExecutingCallback)
+        m_shouldDestroyCallback = true;
+    else
+        m_callback = nullptr;
 }
 
 } // namespace WTF
index 7ec383a6e37c7c4aa8bf8033c77ca68bf323435d..9393c546b59384386a68639cf8267f4efb942af4 100644 (file)
@@ -51,6 +51,8 @@ private:
     GRefPtr<GSource> m_source;
     GRefPtr<GCancellable> m_cancellable;
     Function<gboolean(GIOCondition)> m_callback;
+    bool m_isExecutingCallback { false };
+    bool m_shouldDestroyCallback { false };
 };
 
 } // namespace WTF