diff options
author | Joerg Bornemann <joerg.bornemann@qt.io> | 2017-07-12 14:20:54 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@qt.io> | 2017-07-17 11:20:47 +0000 |
commit | c7ec07d40115bef849574c81d619b629af9434a9 (patch) | |
tree | b794a497d90794719a311b6f86f3e62372771bb1 /src/corelib/io/qwindowspipewriter.cpp | |
parent | 0345608d169d7c59768e461a9ec61bb7563cbaa6 (diff) |
Do not wait in QWindowsPipe{Reader|Writer}::stop()
A deadlock can occur if the user does
QLocalSocket *ls = new QLocalSocket;
ls->moveToThread(t);
...
delete ls;
Then QLocalSocket calls QWindowsPipeReader::stop() in a different thread
than the I/O operation is running in. The waitForNotified(-1) call would
then wait indefinitely until the I/O thread is in alertable wait state
again. Especially on application shut down this might never be the case,
and the application would deadlock.
Solve this by detaching the Overlapped object from the
QWindowsPipe{Reader|Writer} in stop() and delete it in the callback.
Task-number: QTBUG-61643
Change-Id: Ie262d75c5fd92ac7cf7dfcdbf1519050be9fd3c4
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Diffstat (limited to 'src/corelib/io/qwindowspipewriter.cpp')
-rw-r--r-- | src/corelib/io/qwindowspipewriter.cpp | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index d6ee4741e3..7eb6dd0389 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -56,7 +56,7 @@ void QWindowsPipeWriter::Overlapped::clear() QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent) : QObject(parent), handle(pipeWriteEnd), - overlapped(this), + overlapped(nullptr), numberOfBytesToWrite(0), pendingBytesWrittenValue(0), stopped(true), @@ -72,6 +72,7 @@ QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent) QWindowsPipeWriter::~QWindowsPipeWriter() { stop(); + delete overlapped; } bool QWindowsPipeWriter::waitForWrite(int msecs) @@ -122,7 +123,10 @@ void QWindowsPipeWriter::writeFileCompleted(DWORD errorCode, DWORD numberOfBytes OVERLAPPED *overlappedBase) { Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase); - overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered); + if (overlapped->pipeWriter) + overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered); + else + delete overlapped; } /*! @@ -185,13 +189,15 @@ bool QWindowsPipeWriter::write(const QByteArray &ba) if (writeSequenceStarted) return false; - overlapped.clear(); + if (!overlapped) + overlapped = new Overlapped(this); + overlapped->clear(); buffer = ba; numberOfBytesToWrite = buffer.size(); stopped = false; writeSequenceStarted = true; if (!WriteFileEx(handle, buffer.constData(), numberOfBytesToWrite, - &overlapped, &writeFileCompleted)) { + overlapped, &writeFileCompleted)) { writeSequenceStarted = false; numberOfBytesToWrite = 0; buffer.clear(); @@ -208,14 +214,16 @@ void QWindowsPipeWriter::stop() bytesWrittenPending = false; pendingBytesWrittenValue = 0; if (writeSequenceStarted) { - if (!CancelIoEx(handle, &overlapped)) { + overlapped->pipeWriter = nullptr; + if (!CancelIoEx(handle, overlapped)) { const DWORD dwError = GetLastError(); if (dwError != ERROR_NOT_FOUND) { qErrnoWarning(dwError, "QWindowsPipeWriter: CancelIoEx on handle %p failed.", handle); } } - waitForNotification(-1); + overlapped = nullptr; // The object will be deleted in the I/O callback. + writeSequenceStarted = false; } } |