From e8d2e831a4054a7519c60b11d1ba9e6bec85c3bd Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 11 Oct 2017 15:19:17 +0300 Subject: [PATCH] QSslSocket::waitForDisconnected(): flush write buffer before waiting Otherwise, the plain socket might be blocked indefinitely on waiting for socket activity. This issue is tested by tst_QSslSocket::disconnectFromHostWhenConnected() which was unstable in CI. Task-number: QTBUG-64016 Change-Id: I6a1a111dea4d1d1adaf55e6a90c0c5f995a270af Reviewed-by: Edward Welbourne Reviewed-by: Timur Pocheptsov --- src/network/ssl/qsslsocket.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 9d11506fcb..8eba5db9fe 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1686,7 +1686,8 @@ bool QSslSocket::waitForDisconnected(int msecs) if (!d->plainSocket) return false; - if (d->mode == UnencryptedMode) + // Forward to the plain socket unless the connection is secure. + if (d->mode == UnencryptedMode && !d->autoStartHandshake) return d->plainSocket->waitForDisconnected(msecs); QElapsedTimer stopWatch; @@ -1697,6 +1698,17 @@ bool QSslSocket::waitForDisconnected(int msecs) if (!waitForEncrypted(msecs)) return false; } + // We are delaying the disconnect, if the write buffer is not empty. + // So, start the transmission. + if (!d->writeBuffer.isEmpty()) + d->transmit(); + + // At this point, the socket might be disconnected, if disconnectFromHost() + // was called just after the connectToHostEncrypted() call. Also, we can + // lose the connection as a result of the transmit() call. + if (state() == UnconnectedState) + return true; + bool retVal = d->plainSocket->waitForDisconnected(qt_subtract_from_timeout(msecs, stopWatch.elapsed())); if (!retVal) { setSocketState(d->plainSocket->state());