https://codereview.qt-project.org/c/qt/qtbase/+/681531 https://codereview.qt-project.org/c/qt/qtbase/+/682568 From 8e06365bee31ef5a1980b7b24d1564e3d769cfc7 Mon Sep 17 00:00:00 2001 From: Gleb Popov Date: Thu, 2 Oct 2025 13:14:54 +0300 Subject: [PATCH] QNativeSocketEngine::read: Only treat readBytes==0 as a EOF condition with stream sockets This change also covers SOCK_SEQPACKET type of sockets, which isn't great, but allows to avoid an endless polling loop when waiting for read on a disconnected socket. Pick-to: 6.10 Change-Id: I6117b97c2c9b775e9e6fe9757bf4374365e3227d Reviewed-by: Thiago Macieira --- src/network/socket/qnativesocketengine.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git src/network/socket/qnativesocketengine.cpp src/network/socket/qnativesocketengine.cpp index f33e5a26bd94..4c83ef7e5df6 100644 --- src/network/socket/qnativesocketengine.cpp +++ src/network/socket/qnativesocketengine.cpp @@ -910,12 +910,11 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxSize) qint64 readBytes = d->nativeRead(data, maxSize); - // Handle remote close - if (readBytes == 0 && (d->socketType == QAbstractSocket::TcpSocket -#ifndef QT_NO_SCTP - || d->socketType == QAbstractSocket::SctpSocket -#endif - )) { + // Handle remote close. + // Non-datagram socket types signal the EOF state with a zero read. + // Note that it is perfectly fine to have a 0-byte message with datagram + // sockets (SOCK_DGRAM or SOCK_SEQPACKET). + if (readBytes == 0 && d->socketType != QAbstractSocket::UdpSocket) { d->setError(QAbstractSocket::RemoteHostClosedError, QNativeSocketEnginePrivate::RemoteHostClosedErrorString); close(); -- 2.43.0 From a395c091a56781352113670b72ba619367486e7e Mon Sep 17 00:00:00 2001 From: Gleb Popov Date: Tue, 7 Oct 2025 10:53:18 +0300 Subject: [PATCH] Teach QNativeSocketEnginePrivate::fetchConnectionParameters() about SOCK_SEQPACKET Pick-to: 6.10 Change-Id: I4136ef3b4c198e3bd155884bde53171bd34959e4 Reviewed-by: Thiago Macieira --- .../socket/qnativesocketengine_unix.cpp | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git src/network/socket/qnativesocketengine_unix.cpp src/network/socket/qnativesocketengine_unix.cpp index b5fbb5c2e003..bcd9aecdea97 100644 --- src/network/socket/qnativesocketengine_unix.cpp +++ src/network/socket/qnativesocketengine_unix.cpp @@ -1244,6 +1244,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() QT_SOCKOPTLEN_T valueSize = sizeof(int); if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) { if (value == SOCK_STREAM) { + socketType = QAbstractSocket::TcpSocket; #ifndef QT_NO_SCTP if (option(QNativeSocketEngine::MaxStreamsSocketOption) != -1) { socketType = QAbstractSocket::SctpSocket; @@ -1266,17 +1267,23 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() return false; } } - } else { - socketType = QAbstractSocket::TcpSocket; } -#else - socketType = QAbstractSocket::TcpSocket; +#endif + } else if (value == SOCK_DGRAM) { + socketType = QAbstractSocket::UdpSocket; +#ifdef SOCK_SEQPACKET + } else if (value == SOCK_SEQPACKET) { + // We approximate the SEQPACKET socket type to TCP, because + // this enum is actually used to determine if the socket type has + // a notion of connection. SOCK_DGRAM are connectionless, while + // SOCK_STREAM and SOCK_SEQPACKET are connection-orientired. + // This mapping is still suboptimal, because it is possible to send + // a 0-byte packet via SEQPACKET socket and Qt will treat it as + // a disconnect. + socketType = QAbstractSocket::TcpSocket; #endif } else { - if (value == SOCK_DGRAM) - socketType = QAbstractSocket::UdpSocket; - else - socketType = QAbstractSocket::UnknownSocketType; + socketType = QAbstractSocket::UnknownSocketType; } } #if defined (QNATIVESOCKETENGINE_DEBUG) -- 2.43.0