QtNetwork: Better detection of connection failures on Windows

If the error code from WSAConnect is WSAEWOULDBLOCK, then the
operation proceeds but the outcome is not known at that time. We then
check SO_ERROR's value to detect errors. But if that call returns 0
this could indicate that the value is still not know. In this case
we try one more time to increase the chance of getting the correct
value.

This fixed the tst_QNetworkReply::getFromUnreachableIp auto test
on Windows.

Change-Id: I25008aca062b2f823e3d93ebb0ae456d7e4a6ecc
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
This commit is contained in:
Martin Petersson 2012-07-12 12:52:17 +02:00 committed by Qt by Nokia
parent ada38c75cc
commit 4d38a3b2da

View File

@ -683,28 +683,48 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin
// unfinished operation.
int value = 0;
QT_SOCKLEN_T valueSize = sizeof(value);
if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
if (value == WSAECONNREFUSED) {
setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
socketState = QAbstractSocket::UnconnectedState;
break;
bool tryAgain = false;
bool errorDetected = false;
int tries = 0;
do {
if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
if (value == WSAECONNREFUSED) {
setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
socketState = QAbstractSocket::UnconnectedState;
errorDetected = true;
break;
}
if (value == WSAETIMEDOUT) {
setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
socketState = QAbstractSocket::UnconnectedState;
errorDetected = true;
break;
}
if (value == WSAEHOSTUNREACH) {
setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
socketState = QAbstractSocket::UnconnectedState;
errorDetected = true;
break;
}
if (value == WSAEADDRNOTAVAIL) {
setError(QAbstractSocket::NetworkError, AddressNotAvailableErrorString);
socketState = QAbstractSocket::UnconnectedState;
errorDetected = true;
break;
}
if (value == NOERROR) {
// When we get WSAEWOULDBLOCK the outcome was not known, so a
// NOERROR might indicate that the result of the operation
// is still unknown. We try again to increase the chance that we did
// get the correct result.
tryAgain = !tryAgain;
}
}
if (value == WSAETIMEDOUT) {
setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
socketState = QAbstractSocket::UnconnectedState;
break;
}
if (value == WSAEHOSTUNREACH) {
setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
socketState = QAbstractSocket::UnconnectedState;
break;
}
if (value == WSAEADDRNOTAVAIL) {
setError(QAbstractSocket::NetworkError, AddressNotAvailableErrorString);
socketState = QAbstractSocket::UnconnectedState;
break;
}
}
tries++;
} while (tryAgain && (tries < 2));
if (errorDetected)
break;
// fall through
}
case WSAEINPROGRESS: