summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@theqtcompany.com>2015-04-15 15:37:24 +0200
committerJoerg Bornemann <joerg.bornemann@theqtcompany.com>2015-04-16 15:46:01 +0000
commit5ce567c536fde6b7cb93657d14df404f3e270119 (patch)
tree4095caef7fc813f383b06dbcc3c7771c421b0ee5 /src/corelib/io
parenta7f1c97d6096b7f9cc44df275b20d91cc75f7347 (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.cpp35
-rw-r--r--src/corelib/io/qwindowspipereader_p.h1
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;