From ccb693299e6ef633d3ac330961c872a03815c93c Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Fri, 1 Apr 2016 13:19:10 +0300 Subject: Rework toggling the state of read notifier on unbuffered socket To avoid infinite loop on unbuffered socket, previous implementation always disabled the read notifications before emitting a readyRead() signal. So, it's very likely that the socket will toggle the state of notifier twice (on->off->on) in one notification cycle. This patch prevents this unnecessary toggling by deferring the notification disabling in canReadNotification() to the next notification cycle. Change-Id: Iebc5a7ad18a6f40ea1cf63e7f1b12f6c180cbf7a Reviewed-by: Markus Goetz (Woboq GmbH) --- src/network/socket/qabstractsocket.cpp | 12 ++++++++++-- src/network/socket/qabstractsocket_p.h | 1 + src/network/socket/qudpsocket.cpp | 3 ++- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src/network') diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 731afd4e36..03f2ddb968 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -563,6 +563,7 @@ QAbstractSocketPrivate::QAbstractSocketPrivate() cachedSocketDescriptor(-1), readBufferMaxSize(0), isBuffered(false), + hasPendingData(false), connectTimer(0), disconnectTimer(0), hostLookupId(-1), @@ -593,6 +594,7 @@ void QAbstractSocketPrivate::resetSocketLayer() qDebug("QAbstractSocketPrivate::resetSocketLayer()"); #endif + hasPendingData = false; if (socketEngine) { socketEngine->close(); socketEngine->disconnect(); @@ -683,8 +685,13 @@ bool QAbstractSocketPrivate::canReadNotification() qDebug("QAbstractSocketPrivate::canReadNotification()"); #endif - if (!isBuffered) - socketEngine->setReadNotificationEnabled(false); + if (!isBuffered) { + if (hasPendingData) { + socketEngine->setReadNotificationEnabled(false); + return true; + } + hasPendingData = true; + } // If buffered, read data from the socket into the read buffer qint64 newBytes = 0; @@ -2434,6 +2441,7 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize) d->state = QAbstractSocket::UnconnectedState; } else { // Only do this when there was no error + d->hasPendingData = false; d->socketEngine->setReadNotificationEnabled(true); } diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index ab642e039b..3164c96c1e 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -143,6 +143,7 @@ public: qint64 readBufferMaxSize; bool isBuffered; + bool hasPendingData; QTimer *connectTimer; QTimer *disconnectTimer; diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index c406009069..083648bc23 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -398,7 +398,8 @@ qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *addres readBytes = d->socketEngine->readDatagram(data, maxSize); } - d_func()->socketEngine->setReadNotificationEnabled(true); + d->hasPendingData = false; + d->socketEngine->setReadNotificationEnabled(true); if (readBytes < 0) d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString()); return readBytes; -- cgit v1.2.3