From 50c8ec9fa4f9925c825b70c581bd86034e1891d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 8 Feb 2022 14:28:25 +0100 Subject: [PATCH] QAbstractSocket: Don't pretend pause and resume is a stack It only stores one layer of state, and pausing twice in a row will just overwrite the previous state. This doesn't happen often but can happen, especially on Windows if a certificate needs to be looked up in the system certificate stores (socket gets paused) and then a recoverable error occurs in QNAM (socket gets paused again). Fixes: QTBUG-100362 Fixes: QTBUG-63196 Fixes: QTBUG-98476 Pick-to: 6.3 6.2 5.15 Change-Id: Ie524c48e11b6fa8010b78cc1bf3931efe2ce3351 Reviewed-by: Edward Welbourne Reviewed-by: Timur Pocheptsov --- src/network/socket/qabstractsocket.cpp | 47 +++++++++++++++---- src/network/socket/qabstractsocket_p.h | 8 ++-- .../network/access/qnetworkreply/BLACKLIST | 2 - 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 08e6b8c77d..b5228981fc 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -1346,12 +1346,29 @@ void QAbstractSocketPrivate::pauseSocketNotifiers(QAbstractSocket *socket) QAbstractSocketEngine *socketEngine = socket->d_func()->socketEngine; if (!socketEngine) return; - socket->d_func()->prePauseReadSocketNotifierState = socketEngine->isReadNotificationEnabled(); - socket->d_func()->prePauseWriteSocketNotifierState = socketEngine->isWriteNotificationEnabled(); - socket->d_func()->prePauseExceptionSocketNotifierState = socketEngine->isExceptionNotificationEnabled(); - socketEngine->setReadNotificationEnabled(false); - socketEngine->setWriteNotificationEnabled(false); - socketEngine->setExceptionNotificationEnabled(false); + bool read = socketEngine->isReadNotificationEnabled(); + bool write = socketEngine->isWriteNotificationEnabled(); + bool except = socketEngine->isExceptionNotificationEnabled(); + +#ifdef QABSTRACTSOCKET_DEBUG + qDebug() << socketEngine->socketDescriptor() + << "pause notifiers, storing 'true' states, currently read:" << read + << "write:" << write << "except:" << except; +#endif + // We do this if-check to avoid accidentally overwriting any previously stored state + // It will reset to false once the socket is re-enabled. + if (read) { + socket->d_func()->prePauseReadSocketNotifierState = true; + socketEngine->setReadNotificationEnabled(false); + } + if (write) { + socket->d_func()->prePauseWriteSocketNotifierState = true; + socketEngine->setWriteNotificationEnabled(false); + } + if (except) { + socket->d_func()->prePauseExceptionSocketNotifierState = true; + socketEngine->setExceptionNotificationEnabled(false); + } } void QAbstractSocketPrivate::resumeSocketNotifiers(QAbstractSocket *socket) @@ -1359,9 +1376,19 @@ void QAbstractSocketPrivate::resumeSocketNotifiers(QAbstractSocket *socket) QAbstractSocketEngine *socketEngine = socket->d_func()->socketEngine; if (!socketEngine) return; - socketEngine->setReadNotificationEnabled(socket->d_func()->prePauseReadSocketNotifierState); - socketEngine->setWriteNotificationEnabled(socket->d_func()->prePauseWriteSocketNotifierState); - socketEngine->setExceptionNotificationEnabled(socket->d_func()->prePauseExceptionSocketNotifierState); + QAbstractSocketPrivate *priv = socket->d_func(); +#ifdef QABSTRACTSOCKET_DEBUG + qDebug() << socketEngine->socketDescriptor() + << "Maybe resume notifiers, read:" << priv->prePauseReadSocketNotifierState + << "write:" << priv->prePauseWriteSocketNotifierState + << "exception:" << priv->prePauseExceptionSocketNotifierState; +#endif + if (std::exchange(priv->prePauseReadSocketNotifierState, false)) + socketEngine->setReadNotificationEnabled(true); + if (std::exchange(priv->prePauseWriteSocketNotifierState, false)) + socketEngine->setWriteNotificationEnabled(true); + if (std::exchange(priv->prePauseExceptionSocketNotifierState, false)) + socketEngine->setExceptionNotificationEnabled(true); } QAbstractSocketEngine* QAbstractSocketPrivate::getSocketEngine(QAbstractSocket *socket) diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index 83a8afe36d..d2a1378874 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -159,9 +159,9 @@ public: QAbstractSocket::NetworkLayerProtocol preferredNetworkLayerProtocol; - bool prePauseReadSocketNotifierState; - bool prePauseWriteSocketNotifierState; - bool prePauseExceptionSocketNotifierState; + bool prePauseReadSocketNotifierState = false; + bool prePauseWriteSocketNotifierState = false; + bool prePauseExceptionSocketNotifierState = false; static void pauseSocketNotifiers(QAbstractSocket*); static void resumeSocketNotifiers(QAbstractSocket*); static QAbstractSocketEngine* getSocketEngine(QAbstractSocket*); diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index ed3d19197e..977d8be7f5 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -59,8 +59,6 @@ macos macos [putToHttpsSynchronous] osx -[putWithServerClosingConnectionImmediately] -windows-10 [putWithRateLimiting] macos [qtbug13431replyThrottling]