summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp16
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h1
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp32
3 files changed, 48 insertions, 1 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 0ac14c78f6..5726925cb0 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -251,6 +251,20 @@ bool QHttpNetworkConnectionChannel::sendRequest()
return protocolHandler->sendRequest();
}
+/*
+ * Invoke "protocolHandler->sendRequest" using a queued connection.
+ * It's used to return to the event loop before invoking sendRequest when
+ * there's a very real chance that the request could have been aborted
+ * (i.e. after having emitted 'encrypted').
+ */
+void QHttpNetworkConnectionChannel::sendRequestDelayed()
+{
+ QMetaObject::invokeMethod(this, [this] {
+ Q_ASSERT(!protocolHandler.isNull());
+ if (reply)
+ protocolHandler->sendRequest();
+ }, Qt::ConnectionType::QueuedConnection);
+}
void QHttpNetworkConnectionChannel::_q_receiveReply()
{
@@ -1234,7 +1248,7 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
emit reply->encrypted();
}
if (reply)
- sendRequest();
+ sendRequestDelayed();
}
}
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index e9cdae5653..270b3eb9ba 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -174,6 +174,7 @@ public:
void abort();
bool sendRequest();
+ void sendRequestDelayed();
bool ensureConnection();
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 0ef3dc0b61..9c77e156d7 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -392,6 +392,7 @@ private Q_SLOTS:
void ignoreSslErrorsListWithSlot_data();
void ignoreSslErrorsListWithSlot();
void encrypted();
+ void abortOnEncrypted();
void sslConfiguration_data();
void sslConfiguration();
#ifdef QT_BUILD_INTERNAL
@@ -6244,6 +6245,37 @@ void tst_QNetworkReply::encrypted()
reply->deleteLater();
}
+void tst_QNetworkReply::abortOnEncrypted()
+{
+ SslServer server;
+ server.listen();
+ if (!server.isListening())
+ QSKIP("Server fails to listen. Skipping since QTcpServer is covered in another test.");
+
+ server.connect(&server, &SslServer::newEncryptedConnection, [&server]() {
+ connect(server.socket, &QTcpSocket::readyRead, server.socket, []() {
+ // This slot must not be invoked!
+ QVERIFY(false);
+ });
+ });
+
+ QNetworkAccessManager nm;
+ QNetworkReply *reply = nm.get(QNetworkRequest(QUrl(QString("https://localhost:%1").arg(server.serverPort()))));
+ reply->ignoreSslErrors();
+
+ connect(reply, &QNetworkReply::encrypted, [reply, &nm]() {
+ reply->abort();
+ nm.clearConnectionCache();
+ });
+
+ QSignalSpy spyEncrypted(reply, &QNetworkReply::encrypted);
+ QTRY_COMPARE(spyEncrypted.count(), 1);
+
+ // Wait for the socket to be closed again in order to be sure QTcpSocket::readyRead would have been emitted.
+ QTRY_VERIFY(server.socket != nullptr);
+ QTRY_COMPARE(server.socket->state(), QAbstractSocket::UnconnectedState);
+}
+
void tst_QNetworkReply::sslConfiguration()
{
QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/index.html"));