summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Trotsenko <alex1973tr@gmail.com>2015-08-21 13:00:55 +0300
committerAlex Trotsenko <alex1973tr@gmail.com>2015-09-10 12:51:06 +0000
commitc86ca601edfde6e7b6a0769903d86bd48e26d70d (patch)
tree5dc099fa2f0848f8599f664456258db19a68e270
parenta6ec869211d67fed94e3513dc453a96717155121 (diff)
Windows socket engine: do not discard datagram on critical failure
On some network conditions, WSARecvFrom() may return WSAECONNRESET or WSAENETRESET error code to indicate that the connection has been broken and should be reset. According to MSDN documentation, WSAECONNRESET mean that the virtual circuit was reset by the remote side executing a hard or abortive close. Also, it would indicate that a previous send operation resulted in an ICMP "Port Unreachable" message. For a datagram socket, WSAENETRESET indicates that the time to live has expired. Previously, hasPendingDatagram() discarded datagrams with these errors and reported no data available. This behavior is incorrect and can lead to infinite "freezing" of the socket. This patch allows to handle these notifications as a result of the readDatagram() call. Task-number: QTBUG-46552 Change-Id: I7d84babe22d36736b928b4dd4841e30be53d16bd Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com> Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp37
1 files changed, 21 insertions, 16 deletions
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 72f85c831f..708be2dea7 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -1090,8 +1090,11 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
buf.buf = &c;
buf.len = sizeof(c);
DWORD flags = MSG_PEEK;
- if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR)
- return 0;
+ if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) {
+ int err = WSAGetLastError();
+ if (err != WSAECONNRESET && err != WSAENETRESET)
+ return 0;
+ }
}
return nbytes;
}
@@ -1119,14 +1122,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
int err = WSAGetLastError();
if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) {
WS_ERROR_DEBUG(err);
- if (err == WSAECONNRESET || err == WSAENETRESET) {
- // Discard error message to prevent QAbstractSocket from
- // getting this message repeatedly after reenabling the
- // notifiers.
- flags = 0;
- ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
- &storage.a, &storageSize, 0, 0);
- }
+ result = (err == WSAECONNRESET || err == WSAENETRESET);
} else {
// If there's no error, or if our buffer was too small, there must be
// a pending datagram.
@@ -1179,12 +1175,21 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
if (recvResult != SOCKET_ERROR) {
ret = qint64(bytesRead);
break;
- } else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) {
- bufferCount += 5;
- delete[] buf;
- } else if (recvResult == SOCKET_ERROR) {
- WS_ERROR_DEBUG(err);
- ret = -1;
+ } else {
+ switch (err) {
+ case WSAEMSGSIZE:
+ bufferCount += 5;
+ delete[] buf;
+ continue;
+ case WSAECONNRESET:
+ case WSAENETRESET:
+ ret = 0;
+ break;
+ default:
+ WS_ERROR_DEBUG(err);
+ ret = -1;
+ break;
+ }
break;
}
}