summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Trotsenko <alex1973tr@gmail.com>2020-08-18 15:07:38 +0300
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2020-08-26 15:12:32 +0000
commitfb6f62354ff8d29152db7cfa479b2689a25ae7a9 (patch)
tree614e91ba987a15e58b32c723e6203f5ba4578413
parent35ee7ab7ba36218c4495cb9a6195264c1e69c501 (diff)
Synchronize QEventDispatcherWin32::processEvents() with QCoreApplication
QCoreApplication has a special internal mechanism to control whether the event dispatcher should block after delivering the posted events. To handle queued connections in nested loops properly, we should use that functionality. Fixes: QTBUG-85981 Change-Id: I124179a23b26a995cf95ed379e97bfa62c95f42a Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit fe4b246446f721085946e399b96a42eccfcecca8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp4
-rw-r--r--tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp26
2 files changed, 29 insertions, 1 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 34518c4101..65fc7870f2 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -527,6 +527,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
// QCoreApplication::sendPostedEvents() takes care about recursions.
sendPostedEvents();
+ auto threadData = d->threadData.loadRelaxed();
bool canWait;
bool retVal = false;
do {
@@ -617,7 +618,8 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
// still nothing - wait for message or signalled objects
canWait = (!retVal
&& !d->interrupt.loadRelaxed()
- && (flags & QEventLoop::WaitForMoreEvents));
+ && flags.testFlag(QEventLoop::WaitForMoreEvents)
+ && threadData->canWaitLocked());
if (canWait) {
emit aboutToBlock();
waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
diff --git a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
index 85a2dae3b6..7aadd14466 100644
--- a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
+++ b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
@@ -67,6 +67,7 @@ private slots:
void sendPostedEvents_data();
void sendPostedEvents();
void processEventsOnlySendsQueuedEvents();
+ void postedEventsPingPong();
void eventLoopExit();
};
@@ -349,6 +350,31 @@ void tst_QEventDispatcher::processEventsOnlySendsQueuedEvents()
QCOMPARE(object.eventsReceived, 4);
}
+void tst_QEventDispatcher::postedEventsPingPong()
+{
+ QEventLoop mainLoop;
+
+ // We need to have at least two levels of nested loops
+ // for the posted event to get stuck (QTBUG-85981).
+ QMetaObject::invokeMethod(this, [this, &mainLoop]() {
+ QMetaObject::invokeMethod(this, [&mainLoop]() {
+ // QEventLoop::quit() should be invoked on the next
+ // iteration of mainLoop.exec().
+ QMetaObject::invokeMethod(&mainLoop, &QEventLoop::quit,
+ Qt::QueuedConnection);
+ }, Qt::QueuedConnection);
+ mainLoop.processEvents();
+ }, Qt::QueuedConnection);
+
+ // We should use Qt::CoarseTimer on Windows, to prevent event
+ // dispatcher from sending a posted event.
+ QTimer::singleShot(500, Qt::CoarseTimer, [&mainLoop]() {
+ mainLoop.exit(1);
+ });
+
+ QCOMPARE(mainLoop.exec(), 0);
+}
+
void tst_QEventDispatcher::eventLoopExit()
{
// This test was inspired by QTBUG-79477. A particular