diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-05-08 13:22:49 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-05-08 13:26:44 +0200 |
commit | 1fce111809f216383e60f56b57a9f68ccd2b766f (patch) | |
tree | 521d560ae28354ec495ee49e2abf4cfd28303c3f /src/corelib/io/qwindowspipereader.cpp | |
parent | e6ffb36b5517d1d4025718b56423db9bdf0a63f8 (diff) | |
parent | 3545ef41217e3ce4d1bea2b07793fa7a8c1058a6 (diff) |
Merge remote-tracking branch 'origin/5.4' into merge5.5
Conflicts:
src/corelib/global/qglobal.h
src/corelib/io/qnoncontiguousbytedevice_p.h
src/gui/image/qjpeghandler.cpp
src/network/access/qhttpthreaddelegate_p.h
tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
tests/auto/widgets/widgets/qmenubar/BLACKLIST
Change-Id: I01de8c1c28efcedfd7953d05025f54802dc08ab3
Diffstat (limited to 'src/corelib/io/qwindowspipereader.cpp')
-rw-r--r-- | src/corelib/io/qwindowspipereader.cpp | 102 |
1 files changed, 50 insertions, 52 deletions
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index ab2025ee5c..14aad0e193 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -36,7 +36,6 @@ #include <qdebug.h> #include <qelapsedtimer.h> #include <qeventloop.h> -#include <qtimer.h> QT_BEGIN_NAMESPACE @@ -45,13 +44,11 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent) handle(INVALID_HANDLE_VALUE), readBufferMaxSize(0), actualReadBufferSize(0), + stopped(true), readSequenceStarted(false), - emitReadyReadTimer(new QTimer(this)), pipeBroken(false), readyReadEmitted(false) { - emitReadyReadTimer->setSingleShot(true); - connect(emitReadyReadTimer, SIGNAL(timeout()), SIGNAL(readyRead())); dataReadNotifier = new QWinOverlappedIoNotifier(this); connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified); } @@ -73,12 +70,7 @@ static bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped) QWindowsPipeReader::~QWindowsPipeReader() { - if (readSequenceStarted) { - if (qt_cancelIo(handle, &overlapped)) - dataReadNotifier->waitForNotified(-1, &overlapped); - else - qErrnoWarning("QWindowsPipeReader: qt_cancelIo on handle %x failed.", handle); - } + stop(); } /*! @@ -89,9 +81,9 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd) readBuffer.clear(); actualReadBufferSize = 0; handle = hPipeReadEnd; - ZeroMemory(&overlapped, sizeof(overlapped)); pipeBroken = false; readyReadEmitted = false; + stopped = false; if (hPipeReadEnd != INVALID_HANDLE_VALUE) { dataReadNotifier->setHandle(hPipeReadEnd); dataReadNotifier->setEnabled(true); @@ -100,13 +92,24 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd) /*! Stops the asynchronous read sequence. - This function assumes that the file already has been closed. - It does not cancel any I/O operation. + If the read sequence is running then the I/O operation is canceled. */ void QWindowsPipeReader::stop() { - dataReadNotifier->setEnabled(false); + stopped = true; + if (readSequenceStarted) { + if (qt_cancelIo(handle, &overlapped)) { + dataReadNotifier->waitForNotified(-1, &overlapped); + } else { + const DWORD dwError = GetLastError(); + if (dwError != ERROR_NOT_FOUND) { + qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.", + handle); + } + } + } readSequenceStarted = false; + dataReadNotifier->setEnabled(false); handle = INVALID_HANDLE_VALUE; } @@ -119,7 +122,7 @@ qint64 QWindowsPipeReader::bytesAvailable() const } /*! - Stops the asynchronous read sequence. + Copies at most \c{maxlen} bytes from the internal read buffer to \c{data}. */ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen) { @@ -147,9 +150,7 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen) } if (!pipeBroken) { - if (!actualReadBufferSize) - emitReadyReadTimer->stop(); - if (!readSequenceStarted) + if (!readSequenceStarted && !stopped) startAsyncRead(); if (readSoFar == 0) return -2; // signal EWOULDBLOCK @@ -172,13 +173,41 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, { if (&overlapped != notifiedOverlapped) return; - if (!completeAsyncRead(numberOfBytesRead, errorCode)) { + + switch (errorCode) { + case ERROR_SUCCESS: + break; + case ERROR_MORE_DATA: + // This is not an error. We're connected to a message mode + // pipe and the message didn't fit into the pipe's system + // buffer. We will read the remaining data in the next call. + break; + case ERROR_BROKEN_PIPE: + case ERROR_PIPE_NOT_CONNECTED: pipeBroken = true; + break; + default: + emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead")); + pipeBroken = true; + break; + } + + readSequenceStarted = false; + + // After the reader was stopped, the only reason why this function can be called is the + // completion of a cancellation. No signals should be emitted, and no new read sequence should + // be started in this case. + if (stopped) + return; + + if (pipeBroken) { emit pipeClosed(); return; } + + actualReadBufferSize += numberOfBytesRead; + readBuffer.truncate(actualReadBufferSize); startAsyncRead(); - emitReadyReadTimer->stop(); readyReadEmitted = true; emit readyRead(); } @@ -206,6 +235,7 @@ void QWindowsPipeReader::startAsyncRead() char *ptr = readBuffer.reserve(bytesToRead); readSequenceStarted = true; + ZeroMemory(&overlapped, sizeof(overlapped)); if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) { // We get notified by the QWinOverlappedIoNotifier - even in the synchronous case. return; @@ -241,38 +271,6 @@ void QWindowsPipeReader::startAsyncRead() /*! \internal - Sets the correct size of the read buffer after a read operation. - Returns \c false, if an error occurred or the connection dropped. - */ -bool QWindowsPipeReader::completeAsyncRead(DWORD bytesRead, DWORD errorCode) -{ - readSequenceStarted = false; - - switch (errorCode) { - case ERROR_SUCCESS: - break; - case ERROR_MORE_DATA: - // This is not an error. We're connected to a message mode - // pipe and the message didn't fit into the pipe's system - // buffer. We will read the remaining data in the next call. - break; - case ERROR_BROKEN_PIPE: - case ERROR_PIPE_NOT_CONNECTED: - return false; - default: - emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead")); - return false; - } - - actualReadBufferSize += bytesRead; - readBuffer.truncate(actualReadBufferSize); - if (!emitReadyReadTimer->isActive()) - emitReadyReadTimer->start(); - return true; -} - -/*! - \internal Returns the number of available bytes in the pipe. Sets QWindowsPipeReader::pipeBroken to true if the connection is broken. */ |