QLocalSocket/Win: stop reading in close()

After calling close(), the socket can enter 'Closing' state, in which
we try to write buffered data before disconnecting. As the device is
already closed, we must disable any pipe reader activity and clear the
read buffer.

Change-Id: I8994df32bf324325d54dd36cbe1a1ee3f08022d1
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
This commit is contained in:
Alex Trotsenko 2021-10-02 18:10:20 +03:00
parent b689d8dccd
commit 82b86960c0
4 changed files with 24 additions and 5 deletions

View File

@ -104,6 +104,7 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
void QWindowsPipeReader::stop()
{
cancelAsyncRead(Stopped);
pipeBroken = true;
}
/*!
@ -113,6 +114,22 @@ void QWindowsPipeReader::stop()
void QWindowsPipeReader::drainAndStop()
{
cancelAsyncRead(Draining);
pipeBroken = true;
}
/*!
Stops the asynchronous read sequence.
Clears the internal buffer and discards any pending data.
*/
void QWindowsPipeReader::stopAndClear()
{
cancelAsyncRead(Stopped);
readBuffer.clear();
actualReadBufferSize = 0;
// QLocalSocket is supposed to write data in the 'Closing'
// state, so we don't set 'pipeBroken' flag here. Also, avoid
// setting this flag in checkForReadyRead().
lastError = ERROR_SUCCESS;
}
/*!
@ -120,7 +137,6 @@ void QWindowsPipeReader::drainAndStop()
*/
void QWindowsPipeReader::cancelAsyncRead(State newState)
{
pipeBroken = true;
if (state != Running)
return;
@ -147,9 +163,9 @@ void QWindowsPipeReader::cancelAsyncRead(State newState)
}
mutex.unlock();
// Because pipeBroken was set earlier, finish reading to keep the class
// state consistent. Note that signals are not emitted in the call
// below, as the caller is expected to do that synchronously.
// Finish reading to keep the class state consistent. Note that
// signals are not emitted in the call below, as the caller is
// expected to do that synchronously.
consumePending();
}

View File

@ -71,6 +71,7 @@ public:
void startAsyncRead();
void stop();
void drainAndStop();
void stopAndClear();
void setMaxReadBufferSize(qint64 size);
qint64 maxReadBufferSize() const { return readBufferMaxSize; }

View File

@ -396,6 +396,7 @@ void QLocalSocket::close()
Q_D(QLocalSocket);
QIODevice::close();
d->pipeReader->stopAndClear();
d->serverName = QString();
d->fullServerName = QString();
disconnectFromServer();

View File

@ -1372,7 +1372,7 @@ void tst_QLocalSocket::delayedDisconnect()
QVERIFY(serverSocket);
connect(serverSocket, &QLocalSocket::aboutToClose, [serverSocket]() {
QVERIFY(serverSocket->isOpen());
QVERIFY(serverSocket->getChar(nullptr));
QCOMPARE(serverSocket->bytesAvailable(), qint64(1));
});
QVERIFY(socket.putChar(0));
@ -1386,6 +1386,7 @@ void tst_QLocalSocket::delayedDisconnect()
serverSocket->close();
QCOMPARE(serverSocket->state(), QLocalSocket::UnconnectedState);
QVERIFY(!serverSocket->isOpen());
QCOMPARE(serverSocket->bytesAvailable(), qint64(0));
}
void tst_QLocalSocket::removeServer()