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)