QWindowsPipeReader: fix waiting on inactive pipe

To read data from a named pipe, QWindowsPipeReader uses the ReadFileEx()
function which runs asynchronously. When reading is completed and the
thread is in an alertable wait state, the notified() callback is called
by the system, reporting a completion status of that operation. Then the
callback queues a readyRead signal and starts a new sequence. The latter
is skipped if the pipe is broken or the read buffer is full.

Thus, if an application does not run the event loop, the next call to
QWindowsPipeReader::waitForReadyRead() should emit the queued signal
and report true to the caller even if no new read operation was started.

Change-Id: I37102dbb1c00191d93365bfc2e94e743d9f3962a
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
bb10
Alex Trotsenko 2018-04-06 16:09:18 +03:00
parent 38a16b8be0
commit e8733ffc51
2 changed files with 15 additions and 3 deletions

View File

@ -316,15 +316,15 @@ void QWindowsPipeReader::emitPendingReadyRead()
*/
bool QWindowsPipeReader::waitForReadyRead(int msecs)
{
if (!readSequenceStarted)
return false;
if (readyReadPending) {
if (!inReadyRead)
emitPendingReadyRead();
return true;
}
if (!readSequenceStarted)
return false;
if (!waitForNotification(msecs))
return false;

View File

@ -42,6 +42,10 @@
#include <unistd.h> // for unlink()
#endif
#ifdef Q_OS_WIN
#include <QtCore/qt_windows.h>
#endif
Q_DECLARE_METATYPE(QLocalSocket::LocalSocketError)
Q_DECLARE_METATYPE(QLocalSocket::LocalSocketState)
Q_DECLARE_METATYPE(QLocalServer::SocketOption)
@ -629,6 +633,14 @@ void tst_QLocalSocket::readBufferOverflow()
QCOMPARE(client.bytesAvailable(), 0);
#ifdef Q_OS_WIN
serverSocket->write(buffer, readBufferSize);
QVERIFY(serverSocket->waitForBytesWritten());
// ensure the read completion routine is called
SleepEx(100, true);
QVERIFY(client.waitForReadyRead());
QCOMPARE(client.read(buffer, readBufferSize), qint64(readBufferSize));
// Test overflow caused by an asynchronous pipe operation.
client.setReadBufferSize(1);
serverSocket->write(buffer, 2);