Title: [216065] trunk/Source/WebCore
Revision
216065
Author
[email protected]
Date
2017-05-02 01:48:10 -0700 (Tue, 02 May 2017)

Log Message

[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: trunk/Source/WebCore/ChangeLog (216064 => 216065)


--- trunk/Source/WebCore/ChangeLog	2017-05-02 08:39:14 UTC (rev 216064)
+++ trunk/Source/WebCore/ChangeLog	2017-05-02 08:48:10 UTC (rev 216065)
@@ -1,3 +1,25 @@
+2017-04-12  Carlos Garcia Campos  <[email protected]>
+
+        [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-05-01  Zan Dobersek  <[email protected]>
 
         [GCrypt] ECDSA signing and verification support

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp (216064 => 216065)


--- trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2017-05-02 08:39:14 UTC (rev 216064)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2017-05-02 08:48:10 UTC (rev 216065)
@@ -84,17 +84,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;
@@ -143,7 +150,7 @@
 
     RefPtr<PlatformMediaResourceLoader> loader;
     RefPtr<PlatformMediaResource> resource;
-    std::unique_ptr<ResourceHandleStreamingClient> client;
+    RefPtr<ResourceHandleStreamingClient> client;
 
     bool didPassAccessControlCheck;
 
@@ -414,12 +421,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();
@@ -567,10 +577,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
@@ -1095,17 +1104,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;
-#if USE(SOUP)
-            m_session = nullptr;
-#endif
-            m_terminateRunLoopCondition.notifyOne();
-        }
     });
     m_initializeRunLoopCondition.wait(m_initializeRunLoopConditionMutex);
 }
@@ -1116,14 +1114,33 @@
         m_thread->detach();
         m_thread = nullptr;
     }
+}
 
-    if (m_runLoop == &RunLoop::current())
-        m_runLoop->stop();
-    else {
+void ResourceHandleStreamingClient::cleanupAndStopRunLoop()
+{
+    m_resource->clearClient();
+    m_resource->cancel();
+    m_resource = nullptr;
+#if USE(SOUP)
+    m_session = nullptr;
+#endif
+    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
@@ -1133,7 +1150,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);
     });
@@ -1153,7 +1170,8 @@
 
 void ResourceHandleStreamingClient::didReceiveResponse(ResourceHandle*, ResourceResponse&& response)
 {
-    handleResponseReceived(response);
+    if (m_resource)
+        handleResponseReceived(response);
 }
 
 void ResourceHandleStreamingClient::didReceiveData(ResourceHandle*, const char* /* data */, unsigned /* length */, int)
@@ -1163,6 +1181,9 @@
 
 void ResourceHandleStreamingClient::didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&& buffer, int /* encodedLength */)
 {
+    if (!m_resource)
+        return;
+
     for (const auto& segment : buffer.get())
         handleDataReceived(segment->data(), segment->size());
 }
@@ -1169,7 +1190,8 @@
 
 void ResourceHandleStreamingClient::didFinishLoading(ResourceHandle*)
 {
-    handleNotifyFinished();
+    if (m_resource)
+        handleNotifyFinished();
 }
 
 void ResourceHandleStreamingClient::didFail(ResourceHandle*, const ResourceError& error)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to