diff options
-rw-r--r-- | src/serialport/qwinoverlappedionotifier.cpp | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/src/serialport/qwinoverlappedionotifier.cpp b/src/serialport/qwinoverlappedionotifier.cpp index d03b52ae..65d63bba 100644 --- a/src/serialport/qwinoverlappedionotifier.cpp +++ b/src/serialport/qwinoverlappedionotifier.cpp @@ -93,6 +93,7 @@ public: HANDLE hSemaphore = nullptr; HANDLE hResultsMutex = nullptr; QAtomicInt waiting; + QAtomicInt signalSent; QQueue<IOResult> results; }; @@ -361,14 +362,31 @@ void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCod results.enqueue(IOResult(numberOfBytes, errorCode, overlapped)); ReleaseMutex(hResultsMutex); ReleaseSemaphore(hSemaphore, 1, NULL); - if (!waiting) + // Do not send a signal if we didn't process the previous one. + // This is done to prevent soft memory leaks when working in a completely + // synchronous way. + if (!waiting && !signalSent.loadAcquire()) { + signalSent.storeRelease(1); emit q->_q_notify(); + } } void QWinOverlappedIoNotifierPrivate::_q_notified() { - if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) - dispatchNextIoResult(); + Q_Q(QWinOverlappedIoNotifier); + signalSent.storeRelease(0); // signal processed - ready for a new one + if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) { + // As we do not queue signals anymore, we need to process the whole + // queue at once. + WaitForSingleObject(hResultsMutex, INFINITE); + QQueue<IOResult> values; + results.swap(values); + ReleaseMutex(hResultsMutex); + while (!values.empty()) { + IOResult ioresult = values.dequeue(); + emit q->notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped); + } + } } OVERLAPPED *QWinOverlappedIoNotifierPrivate::dispatchNextIoResult() |