From b5f2bf1a71d926b9bb04101b49a11fd641aad14f Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 6 Oct 2017 13:09:57 +0200 Subject: [PATCH] Fix QWinEventNotifier for auto-reset events Auto-reset events are automatically reset to non-signaled when we get notified about the signaled state. This implies that we cannot check the event state again in activateEventNotifiers. Instead, store the signaled state in a QAtomicInt and test and decrement that. This amends commit 85403d0a. Task-number: QTBUG-63555 Change-Id: I0adee3d2929783f98d91060f9106c8b5266d72fa Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qeventdispatcher_win.cpp | 3 ++- src/corelib/kernel/qwineventnotifier.cpp | 2 ++ src/corelib/kernel/qwineventnotifier_p.h | 2 ++ .../qwineventnotifier/tst_qwineventnotifier.cpp | 11 ++++++++++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 569fbc27968..bbd442d5704 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -942,7 +942,8 @@ void QEventDispatcherWin32::activateEventNotifiers() for (int i = d->winEventNotifierList.count(); --i >= 0;) { QWinEventNotifier *notifier = d->winEventNotifierList.at(i); QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); - if (WaitForSingleObject(nd->handleToEvent, 0) == WAIT_OBJECT_0) { + if (nd->signaledCount.load() != 0) { + --nd->signaledCount; nd->unregisterWaitObject(); d->activateEventNotifier(notifier); } diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 6bfa6ca7294..362111a2c8c 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -157,6 +157,7 @@ void QWinEventNotifier::setHandle(HANDLE hEvent) Q_D(QWinEventNotifier); setEnabled(false); d->handleToEvent = hEvent; + d->signaledCount = 0; } /*! @@ -254,6 +255,7 @@ static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/) QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.load(); QEventDispatcherWin32Private *edp = QEventDispatcherWin32Private::get( static_cast(eventDispatcher)); + ++nd->signaledCount; SetEvent(edp->winEventNotifierActivatedEvent); } diff --git a/src/corelib/kernel/qwineventnotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h index bddeaaf1346..8bb2c3159a2 100644 --- a/src/corelib/kernel/qwineventnotifier_p.h +++ b/src/corelib/kernel/qwineventnotifier_p.h @@ -54,6 +54,7 @@ #include "qwineventnotifier.h" #include +#include #include QT_BEGIN_NAMESPACE @@ -73,6 +74,7 @@ public: HANDLE handleToEvent; HANDLE waitHandle = NULL; + QAtomicInt signaledCount; bool enabled; }; diff --git a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp index 304f6121a58..15a39b62c0f 100644 --- a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp +++ b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp @@ -41,6 +41,7 @@ protected slots: void simple_activated(); void simple_timerSet(); private slots: + void simple_data(); void simple(); void manyNotifiers(); @@ -61,9 +62,17 @@ void tst_QWinEventNotifier::simple_timerSet() SetEvent((HANDLE)simpleHEvent); } +void tst_QWinEventNotifier::simple_data() +{ + QTest::addColumn("resetManually"); + QTest::newRow("manual_reset") << true; + QTest::newRow("auto_reset") << false; +} + void tst_QWinEventNotifier::simple() { - simpleHEvent = CreateEvent(0, true, false, 0); + QFETCH(bool, resetManually); + simpleHEvent = CreateEvent(0, resetManually, false, 0); QVERIFY(simpleHEvent); QWinEventNotifier n(simpleHEvent);