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 <edward.welbourne@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
bb10
Alex Trotsenko 2017-10-11 15:19:17 +03:00
parent 754b636053
commit e8d2e831a4
1 changed files with 13 additions and 1 deletions

View File

@ -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());