diff options
author | Joerg Bornemann <joerg.bornemann@theqtcompany.com> | 2015-04-15 15:37:24 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@theqtcompany.com> | 2015-04-16 15:46:01 +0000 |
commit | 5ce567c536fde6b7cb93657d14df404f3e270119 (patch) | |
tree | 4095caef7fc813f383b06dbcc3c7771c421b0ee5 /src/corelib/io | |
parent | a7f1c97d6096b7f9cc44df275b20d91cc75f7347 (diff) |
let QWindowsPipeReader::stop() cancel the current I/O operation
In rare cases the I/O operation was still running after the destructor
was running, which then modified free'd memory and caused a malformed
heap. To prevent this, we ensure that QWindowsPipeReader::stop() cancels
a running I/O operation and sets the readSequenceStarted flag correctly.
Also, we prevent the start of a new read operation after we called stop().
Change-Id: If8a28bdf23a39a0e88c1770a6f66e2b24ea426bb
Task-number: QTBUG-45601
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qwindowspipereader.cpp | 35 | ||||
-rw-r--r-- | src/corelib/io/qwindowspipereader_p.h | 1 |
2 files changed, 26 insertions, 10 deletions
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index cc407dbed9..4ed9674f36 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -44,6 +44,7 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent) handle(INVALID_HANDLE_VALUE), readBufferMaxSize(0), actualReadBufferSize(0), + stopped(true), readSequenceStarted(false), pipeBroken(false), readyReadEmitted(false) @@ -69,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(); } /*! @@ -87,6 +83,7 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd) handle = hPipeReadEnd; pipeBroken = false; readyReadEmitted = false; + stopped = false; if (hPipeReadEnd != INVALID_HANDLE_VALUE) { dataReadNotifier->setHandle(hPipeReadEnd); dataReadNotifier->setEnabled(true); @@ -95,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; } @@ -142,7 +150,7 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen) } if (!pipeBroken) { - if (!readSequenceStarted) + if (!readSequenceStarted && !stopped) startAsyncRead(); if (readSoFar == 0) return -2; // signal EWOULDBLOCK @@ -185,6 +193,13 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, } 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; diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h index 7651093b05..b0a23e1a51 100644 --- a/src/corelib/io/qwindowspipereader_p.h +++ b/src/corelib/io/qwindowspipereader_p.h @@ -97,6 +97,7 @@ private: qint64 readBufferMaxSize; QRingBuffer readBuffer; int actualReadBufferSize; + bool stopped; bool readSequenceStarted; bool pipeBroken; bool readyReadEmitted; |