summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorAlex Trotsenko <alex1973tr@gmail.com>2019-08-19 14:20:11 +0300
committerAlex Trotsenko <alex1973tr@gmail.com>2019-08-29 09:12:29 +0000
commit81408c0e76616b127c46779dc14bbcf084a3d87b (patch)
tree2cdb7c148648e4aa4142ac0c5f4bb58c7b19548d /tests
parent2602209f545ea3873f0dc880c258669a508d283a (diff)
QEventDispatcherWin32: avoid livelock in a foreign event loop
According to Windows docs, GetMessage() function retrieves the messages from the input queue in defined order, where posted messages are processed ahead of input messages, even if they were posted later. Therefore, if the application produces a posted event permanently, as a result of processing that event, user input messages may be blocked due to hard CPU usage by the application. It's not a problem, if an internal Qt event loop is running. By calling sendPostedEvents() on the beginning of processEvents(), we are sending posted events only once per iteration. However, during execution of the foreign loop, we should artificially lower the priority of the WM_QT_SENDPOSTEDEVENTS message in order to enable delivery of other input messages. To solve the problem, it is proposed to postpone the WM_QT_SENDPOSTEDEVENTS message until the message queue becomes empty, as it works for the internal loop. Task-number: QTBUG-77464 Change-Id: I8dedb6837c6fc41aa6f497e67ab2352c2b4f3772 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp
index 19c5c8a4a0..3d1876f00f 100644
--- a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp
+++ b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp
@@ -36,6 +36,7 @@
#include <QtNetwork/qtcpserver.h>
#include <QtNetwork/qtcpsocket.h>
#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qtimer.h>
#include <QtCore/qt_windows.h>
@@ -49,7 +50,7 @@ class tst_NoQtEventLoop : public QObject
private slots:
void consumeMouseEvents();
void consumeSocketEvents();
-
+ void deliverEventsInLivelock();
};
class Window : public QRasterWindow
@@ -312,6 +313,34 @@ void tst_NoQtEventLoop::consumeSocketEvents()
QVERIFY(server.hasPendingConnections());
}
+void tst_NoQtEventLoop::deliverEventsInLivelock()
+{
+ int argc = 1;
+ char *argv[] = { const_cast<char *>("test"), 0 };
+ QGuiApplication app(argc, argv);
+
+ QTimer livelockTimer;
+ livelockTimer.start(0);
+ QTimer::singleShot(100, Qt::CoarseTimer, &livelockTimer, &QTimer::stop);
+
+ QElapsedTimer elapsedTimer;
+ elapsedTimer.start();
+
+ // Exec own message loop
+ MSG msg;
+ forever {
+ if (elapsedTimer.hasExpired(3000) || !livelockTimer.isActive())
+ break;
+
+ if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+ }
+
+ QVERIFY(!livelockTimer.isActive());
+}
+
#include <tst_noqteventloop.moc>
QTEST_APPLESS_MAIN(tst_NoQtEventLoop)