From 4fa6a7a7c7e15a560bd8503fb5c0dc2e6d1024c1 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 21 Jan 2016 18:38:47 +0100 Subject: Fix deadlock on QWebEngineUrlRequestJob::fail URLRequestCustomJob::notifyFailure calls NotifyStartError(status), which in turn will result in a call to URLRequestCustomJob::Kill. We must release the lock of m_mutex before calling NotifyStartError, otherwise m_mutex.lock() will wait forever in Kill. Change-Id: I319e45049766c2192dfc46a91b352b92ec677bc6 Task-number: QTBUG-50160 Reviewed-by: Allan Sandfeld Jensen --- src/core/url_request_custom_job.cpp | 12 +++++++---- .../qwebengineprofile/tst_qwebengineprofile.cpp | 23 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/core/url_request_custom_job.cpp b/src/core/url_request_custom_job.cpp index 1b6f1c767..907f71c2e 100644 --- a/src/core/url_request_custom_job.cpp +++ b/src/core/url_request_custom_job.cpp @@ -222,13 +222,17 @@ void URLRequestCustomJob::fail(int error) void URLRequestCustomJob::notifyFailure() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - QMutexLocker lock(&m_mutex); + m_mutex.lock(); if (m_device) m_device->close(); - if (m_started) - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, m_error)); + const URLRequestStatus status(URLRequestStatus::FAILED, m_error); + const bool started = m_started; + m_mutex.unlock(); + + if (started) + NotifyDone(status); else - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, m_error)); + NotifyStartError(status); } void URLRequestCustomJob::startAsync() diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 7a89e2439..0ad460634 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -50,6 +50,7 @@ private Q_SLOTS: void defaultProfile(); void profileConstructors(); void urlSchemeHandlers(); + void urlSchemeHandlerFailRequest(); }; void tst_QWebEngineProfile::defaultProfile() @@ -147,5 +148,27 @@ void tst_QWebEngineProfile::urlSchemeHandlers() QVERIFY(toPlainTextSync(view.page()) != url.toString()); } +class FailingUrlSchemeHandler : public QWebEngineUrlSchemeHandler +{ +public: + void requestStarted(QWebEngineUrlRequestJob *job) override + { + job->fail(QWebEngineUrlRequestJob::RequestFailed); + } +}; + +void tst_QWebEngineProfile::urlSchemeHandlerFailRequest() +{ + FailingUrlSchemeHandler handler; + QWebEngineProfile profile; + profile.installUrlSchemeHandler("foo", &handler); + QWebEngineView view; + QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool))); + view.setPage(new QWebEnginePage(&profile, &view)); + view.load(QUrl(QStringLiteral("foo://bar"))); + QVERIFY(loadFinishedSpy.wait()); + QVERIFY(toPlainTextSync(view.page()).isEmpty()); +} + QTEST_MAIN(tst_QWebEngineProfile) #include "tst_qwebengineprofile.moc" -- cgit v1.2.3