Title: [216489] releases/WebKitGTK/webkit-2.14/Source/WebCore
Revision
216489
Author
carlo...@webkit.org
Date
2017-05-09 02:58:24 -0700 (Tue, 09 May 2017)

Log Message

Merge r216065 - [GTK] Crash at WebCore::ResourceHandle::clearClient() when streaming live video from dailymotion
https://bugs.webkit.org/show_bug.cgi?id=169725

Reviewed by Michael Catanzaro.

Make ResourceHandleStreamingClient refcounted and add an invalidate method to do the cleanup in the networking
thread while keeping a reference.

* platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
(webKitWebSrcStop): Call invalidate before reseting client pointer.
(webKitWebSrcStart): Ditto.
(ResourceHandleStreamingClient::ResourceHandleStreamingClient): Remove all cleanup code after the run loop run call.
(ResourceHandleStreamingClient::~ResourceHandleStreamingClient): Just detach the thread.
(ResourceHandleStreamingClient::invalidate): Schedule a task on the networking thread to clean up and fiish the
run loop, protecting this.
(ResourceHandleStreamingClient::setDefersLoading): Protect this.
(ResourceHandleStreamingClient::didReceiveResponse): Do nothing if client was invalidated.
(ResourceHandleStreamingClient::didReceiveBuffer): Ditto.
(ResourceHandleStreamingClient::didFinishLoading): Ditto.

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.14/Source/WebCore/ChangeLog (216488 => 216489)


--- releases/WebKitGTK/webkit-2.14/Source/WebCore/ChangeLog	2017-05-09 09:41:49 UTC (rev 216488)
+++ releases/WebKitGTK/webkit-2.14/Source/WebCore/ChangeLog	2017-05-09 09:58:24 UTC (rev 216489)
@@ -1,3 +1,25 @@
+2017-04-12  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        [GTK] Crash at WebCore::ResourceHandle::clearClient() when streaming live video from dailymotion
+        https://bugs.webkit.org/show_bug.cgi?id=169725
+
+        Reviewed by Michael Catanzaro.
+
+        Make ResourceHandleStreamingClient refcounted and add an invalidate method to do the cleanup in the networking
+        thread while keeping a reference.
+
+        * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
+        (webKitWebSrcStop): Call invalidate before reseting client pointer.
+        (webKitWebSrcStart): Ditto.
+        (ResourceHandleStreamingClient::ResourceHandleStreamingClient): Remove all cleanup code after the run loop run call.
+        (ResourceHandleStreamingClient::~ResourceHandleStreamingClient): Just detach the thread.
+        (ResourceHandleStreamingClient::invalidate): Schedule a task on the networking thread to clean up and fiish the
+        run loop, protecting this.
+        (ResourceHandleStreamingClient::setDefersLoading): Protect this.
+        (ResourceHandleStreamingClient::didReceiveResponse): Do nothing if client was invalidated.
+        (ResourceHandleStreamingClient::didReceiveBuffer): Ditto.
+        (ResourceHandleStreamingClient::didFinishLoading): Ditto.
+
 2017-04-07  Alex Christensen  <achristen...@webkit.org>
 
         REGRESSION(r204512): WebSocket errors with "Failed to send WebSocket frame."  if too much data is sent

Modified: releases/WebKitGTK/webkit-2.14/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp (216488 => 216489)


--- releases/WebKitGTK/webkit-2.14/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2017-05-09 09:41:49 UTC (rev 216488)
+++ releases/WebKitGTK/webkit-2.14/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2017-05-09 09:58:24 UTC (rev 216489)
@@ -80,17 +80,24 @@
         void loadFinished(PlatformMediaResource&) override;
 };
 
-class ResourceHandleStreamingClient : public ResourceHandleClient, public StreamingClient {
-    WTF_MAKE_NONCOPYABLE(ResourceHandleStreamingClient); WTF_MAKE_FAST_ALLOCATED;
+class ResourceHandleStreamingClient : public ThreadSafeRefCounted<ResourceHandleStreamingClient>, public ResourceHandleClient, public StreamingClient {
     public:
-        ResourceHandleStreamingClient(WebKitWebSrc*, ResourceRequest&&);
+        static Ref<ResourceHandleStreamingClient> create(WebKitWebSrc* src, ResourceRequest&& request)
+        {
+            return adoptRef(*new ResourceHandleStreamingClient(src, WTFMove(request)));
+        }
         virtual ~ResourceHandleStreamingClient();
 
+        void invalidate();
+
         // StreamingClient virtual methods.
         bool loadFailed() const;
         void setDefersLoading(bool);
 
     private:
+        ResourceHandleStreamingClient(WebKitWebSrc*, ResourceRequest&&);
+        void cleanupAndStopRunLoop();
+
         // ResourceHandleClient virtual methods.
 #if USE(SOUP)
         char* getOrCreateReadBuffer(size_t requestedSize, size_t& actualSize) override;
@@ -135,7 +142,7 @@
 
     RefPtr<PlatformMediaResourceLoader> loader;
     RefPtr<PlatformMediaResource> resource;
-    std::unique_ptr<ResourceHandleStreamingClient> client;
+    RefPtr<ResourceHandleStreamingClient> client;
 
     bool didPassAccessControlCheck;
 
@@ -404,12 +411,15 @@
         });
     }
 
+    if (priv->client) {
+        priv->client->invalidate();
+        priv->client = nullptr;
+    }
+
     WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
 
     bool wasSeeking = std::exchange(priv->isSeeking, false);
 
-    priv->client = nullptr;
-
     if (priv->buffer) {
         unmapGstBuffer(priv->buffer.get());
         priv->buffer.clear();
@@ -557,10 +567,9 @@
     request.setHTTPHeaderField(HTTPHeaderName::IcyMetadata, "1");
 
     if (!priv->player || !priv->createdInMainThread) {
-        priv->client = std::make_unique<ResourceHandleStreamingClient>(src, WTFMove(request));
+        priv->client = ResourceHandleStreamingClient::create(src, WTFMove(request));
         if (priv->client->loadFailed()) {
             GST_ERROR_OBJECT(src, "Failed to setup streaming client");
-            priv->client = nullptr;
             locker.unlock();
             webKitWebSrcStop(src);
         } else
@@ -1080,14 +1089,6 @@
 
         m_runLoop->dispatch([this] { m_resource->setDefersLoading(false); });
         m_runLoop->run();
-        {
-            LockHolder locker(m_terminateRunLoopConditionMutex);
-            m_runLoop = nullptr;
-            m_resource->clearClient();
-            m_resource->cancel();
-            m_resource = nullptr;
-            m_terminateRunLoopCondition.notifyOne();
-        }
     });
     m_initializeRunLoopCondition.wait(m_initializeRunLoopConditionMutex);
 }
@@ -1098,14 +1099,30 @@
         detachThread(m_thread);
         m_thread = 0;
     }
+}
 
-    if (m_runLoop == &RunLoop::current())
-        m_runLoop->stop();
-    else {
+void ResourceHandleStreamingClient::cleanupAndStopRunLoop()
+{
+    m_resource->clearClient();
+    m_resource->cancel();
+    m_resource = nullptr;
+    m_runLoop->stop();
+}
+
+void ResourceHandleStreamingClient::invalidate()
+{
+    if (m_runLoop == &RunLoop::current()) {
+        cleanupAndStopRunLoop();
+        return;
+    }
+
+    LockHolder locker(m_terminateRunLoopConditionMutex);
+    m_runLoop->dispatch([this, protectedThis = makeRef(*this)] {
+        cleanupAndStopRunLoop();
         LockHolder locker(m_terminateRunLoopConditionMutex);
-        m_runLoop->stop();
-        m_terminateRunLoopCondition.wait(m_terminateRunLoopConditionMutex);
-    }
+        m_terminateRunLoopCondition.notifyOne();
+    });
+    m_terminateRunLoopCondition.wait(m_terminateRunLoopConditionMutex);
 }
 
 bool ResourceHandleStreamingClient::loadFailed() const
@@ -1115,7 +1132,7 @@
 
 void ResourceHandleStreamingClient::setDefersLoading(bool defers)
 {
-    m_runLoop->dispatch([this, defers] {
+    m_runLoop->dispatch([this, protectedThis = makeRef(*this), defers] {
         if (m_resource)
             m_resource->setDefersLoading(defers);
     });
@@ -1135,7 +1152,8 @@
 
 void ResourceHandleStreamingClient::didReceiveResponse(ResourceHandle*, ResourceResponse&& response)
 {
-    handleResponseReceived(response);
+    if (m_resource)
+        handleResponseReceived(response);
 }
 
 void ResourceHandleStreamingClient::didReceiveData(ResourceHandle*, const char* /* data */, unsigned /* length */, int)
@@ -1145,6 +1163,9 @@
 
 void ResourceHandleStreamingClient::didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&& buffer, int /* encodedLength */)
 {
+    if (!m_resource)
+        return;
+
     // This pattern is suggested by SharedBuffer.h.
     const char* segment;
     unsigned position = 0;
@@ -1156,7 +1177,8 @@
 
 void ResourceHandleStreamingClient::didFinishLoading(ResourceHandle*, double)
 {
-    handleNotifyFinished();
+    if (m_resource)
+        handleNotifyFinished();
 }
 
 void ResourceHandleStreamingClient::didFail(ResourceHandle*, const ResourceError& error)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to