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 <edward.welbourne@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
bb10
Mårten Nordheim 2022-02-08 14:28:25 +01:00
parent f3d89adf6d
commit 50c8ec9fa4
3 changed files with 41 additions and 16 deletions

View File

@ -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)

View File

@ -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*);

View File

@ -59,8 +59,6 @@ macos
macos
[putToHttpsSynchronous]
osx
[putWithServerClosingConnectionImmediately]
windows-10
[putWithRateLimiting]
macos
[qtbug13431replyThrottling]