fix growth of event queue in QWinOverlappedIoNotifier::waitFor*

Do not emit _q_notified when we're in a wait function. Otherwise,
the queued signals could pile up in the event queue.

Task-number: QTBUG-48653
Change-Id: I071863e2356e17c7004e3b7ca359967cb115e343
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
bb10
Joerg Bornemann 2015-10-08 18:07:00 +02:00
parent b7c4f15d67
commit c20f92a0fa
1 changed files with 51 additions and 19 deletions

View File

@ -33,6 +33,7 @@
#include "qwinoverlappedionotifier_p.h"
#include <qdebug.h>
#include <qatomic.h>
#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qpointer.h>
@ -99,6 +100,7 @@ public:
{
}
OVERLAPPED *waitForAnyNotified(int msecs);
void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
OVERLAPPED *_q_notified();
@ -108,6 +110,7 @@ public:
HANDLE hHandle;
HANDLE hSemaphore;
HANDLE hResultsMutex;
QAtomicInt waiting;
QQueue<IOResult> results;
};
@ -286,6 +289,47 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled)
d->iocp->unregisterNotifier(d);
}
OVERLAPPED *QWinOverlappedIoNotifierPrivate::waitForAnyNotified(int msecs)
{
if (!iocp->isRunning()) {
qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier.");
return 0;
}
if (msecs == 0)
iocp->drainQueue();
const DWORD wfso = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
switch (wfso) {
case WAIT_OBJECT_0:
ReleaseSemaphore(hSemaphore, 1, NULL);
return _q_notified();
case WAIT_TIMEOUT:
return 0;
default:
qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed.");
return 0;
}
}
class QScopedAtomicIntIncrementor
{
public:
QScopedAtomicIntIncrementor(QAtomicInt &i)
: m_int(i)
{
++m_int;
}
~QScopedAtomicIntIncrementor()
{
--m_int;
}
private:
QAtomicInt &m_int;
};
/*!
* Wait synchronously for any notified signal.
*
@ -296,24 +340,9 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled)
OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
{
Q_D(QWinOverlappedIoNotifier);
if (!d->iocp->isRunning()) {
qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier.");
return 0;
}
if (msecs == 0)
d->iocp->drainQueue();
switch (WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs))) {
case WAIT_OBJECT_0:
ReleaseSemaphore(d->hSemaphore, 1, NULL);
return d->_q_notified();
case WAIT_TIMEOUT:
return 0;
default:
qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed.");
return 0;
}
QScopedAtomicIntIncrementor saii(d->waiting);
OVERLAPPED *result = d->waitForAnyNotified(msecs);
return result;
}
/*!
@ -324,6 +353,8 @@ OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
*/
bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
{
Q_D(QWinOverlappedIoNotifier);
QScopedAtomicIntIncrementor saii(d->waiting);
int t = msecs;
QElapsedTimer stopWatch;
stopWatch.start();
@ -350,7 +381,8 @@ void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCod
results.enqueue(IOResult(numberOfBytes, errorCode, overlapped));
ReleaseMutex(hResultsMutex);
ReleaseSemaphore(hSemaphore, 1, NULL);
emit q->_q_notify();
if (!waiting)
emit q->_q_notify();
}
OVERLAPPED *QWinOverlappedIoNotifierPrivate::_q_notified()