From 30245c8515bdac93971520b78bd867eadb813ec2 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 1 Mar 2021 07:56:01 +0100 Subject: Skip tst_QOpenGL::glxContext test on Wayland This test depends on XCB, but is only protected by a build-time flag, so it will be executed as long as XCB is available at build-time. Do as with the offscreen backend and just skip it when a different platform plugin is in use. Task-number: QTBUG-91418 Change-Id: Ida076dc81d0740af2cec164bd40ca10d16345f05 Reviewed-by: Paul Olav Tvete --- tests/auto/gui/qopengl/tst_qopengl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp index 9e66ec9a43..e2e7f153a0 100644 --- a/tests/auto/gui/qopengl/tst_qopengl.cpp +++ b/tests/auto/gui/qopengl/tst_qopengl.cpp @@ -1480,6 +1480,9 @@ void tst_QOpenGL::glxContextWrap() if (QGuiApplication::platformName().startsWith(QLatin1String("offscreen"), Qt::CaseInsensitive)) QSKIP("Offscreen: This fails."); + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Fails on Wayland."); + QWindow *window = new QWindow; window->setSurfaceType(QWindow::OpenGLSurface); window->setGeometry(0, 0, 10, 10); -- cgit v1.2.3 From ea310c1d0f4d9bb66c118407cc9e70e6e2a2d724 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 1 Mar 2021 08:20:45 +0100 Subject: Fix tst_QDialog::keepPositionOnClose on Wayland The test assumed that dialog.move() would actually move the dialog box to the requested location, which is an invalid assumption on Wayland. Since the objective of the test is not to check if move() works this way, but to check whether the dialog box shows up in the same location when it is re-shown, we actually fetch the pos after showing it the first time, rather than assume this is the same as the requested one. Task-number: QTBUG-91418 Change-Id: Ifa21fa08429f198988f90d7ee328e4f35a4764c2 Reviewed-by: Friedemann Kleint Reviewed-by: Paul Olav Tvete --- tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index 53c33255bf..6a59edca10 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -552,10 +552,11 @@ void tst_QDialog::keepPositionOnClose() dialog.setWindowTitle(QTest::currentTestFunction()); const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); dialog.resize(availableGeometry.size() / 4); - const QPoint pos = availableGeometry.topLeft() + QPoint(100, 100); + QPoint pos = availableGeometry.topLeft() + QPoint(100, 100); dialog.move(pos); dialog.show(); QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + pos = dialog.pos(); dialog.close(); dialog.windowHandle()->destroy(); // Emulate a click on close by destroying the window. QTest::qWait(50); -- cgit v1.2.3 From d16b171f1b10deaaa11ae19d4f719344965e9c95 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 26 Feb 2021 13:06:33 +0100 Subject: Make tst_shortcut pass on Wayland There was a race condition in the test, since the window might be exposed before the event to activate the application has been received. And the short cut is not triggered before the application is active, which means it could just be discarded and the window would never be closed. This happened consistently when testing on Wayland. Task-number: QTBUG-91418 Change-Id: I40cb143985175f5f2b5405e9502a48475c93074a Reviewed-by: Paul Olav Tvete --- tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp index fc230f98e2..777f486263 100644 --- a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp +++ b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp @@ -74,6 +74,7 @@ void tst_QShortcut::trigger() new QShortcut(Qt::CTRL | Qt::Key_Q, &w, SLOT(close())); w.show(); QVERIFY(QTest::qWaitForWindowExposed(&w)); + QTRY_VERIFY(QGuiApplication::applicationState() == Qt::ApplicationActive); sendKey(&w, Qt::Key_Q, 'q', Qt::ControlModifier); QTRY_VERIFY(!w.isVisible()); } -- cgit v1.2.3 From 02bc441553d1eb0738293cc37d5398a74d2aaed9 Mon Sep 17 00:00:00 2001 From: Zhang Yong Date: Thu, 11 Mar 2021 17:21:29 +0800 Subject: The conditional statement is missing parentheses Add a ')' to the judgment statement. Change-Id: Iadfdfb7643bc5224cb3029a2abb42c3c14982eef Reviewed-by: Giuseppe D'Angelo --- src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp index 35c06f842e..5858b6a78d 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp @@ -53,7 +53,7 @@ { QDeadlineTimer deadline(msecs); do { - if (readFromDevice(deadline.remainingTime()) + if (readFromDevice(deadline.remainingTime())) break; waitForReadyRead(deadline); } while (!deadline.hasExpired()); -- cgit v1.2.3 From f274f91cebb0a4fd2ebe37bb3a605c47d6acd404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Fri, 5 Mar 2021 14:33:01 +0100 Subject: QEventDispatcher(Win): Always honor interrupted status to avoid races There may be a race where e.g. thread 'B' is woken up by a queued invoke. At the same time thread 'A' asks 'B' to quit, which will set various atomics (some important ones are 'interrupt' in the dispatcher and 'exit' in the event loop), but it does _not_ try to send another wake since there is already an unhandled wake triggered by 'B' itself. Sadly 'B' reads the 'exit' atomic before 'A' updates it. Then, slightly before, 'B' sets 'interrupt' back to 0, 'A' write 1 to it, meaning 'A's interrupt is ignored. Then, since there is no interrupt, 'B' goes back to waiting for events, leaving the thread alive and running instead of quitting. Maybe this has unforeseen consequences (one consequence is that it will return and re-enter the event dispatcher once more, possible unnecessarily) Fixes: QTBUG-91539 Pick-to: 6.1 6.0 5.15 Change-Id: Ie6f861f42ffddf4817d5c8af2d764abe9d9103c2 Reviewed-by: Alex Trotsenko Reviewed-by: Volker Hilsheimer Reviewed-by: Thiago Macieira --- src/corelib/kernel/qeventdispatcher_win.cpp | 6 ++++- .../qeventdispatcher/tst_qeventdispatcher.cpp | 27 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 19604de32f..80297feef1 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -475,13 +475,17 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherWin32); - d->interrupt.storeRelaxed(false); + // We don't know _when_ the interrupt occurred so we have to honor it. + const bool wasInterrupted = d->interrupt.fetchAndStoreRelaxed(false); emit awake(); // To prevent livelocks, send posted events once per iteration. // QCoreApplication::sendPostedEvents() takes care about recursions. sendPostedEvents(); + if (wasInterrupted) + return false; + auto threadData = d->threadData.loadRelaxed(); bool canWait; bool retVal = false; diff --git a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp index 8d69314fa5..21aee94e5d 100644 --- a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp +++ b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp @@ -71,6 +71,7 @@ private slots: void processEventsOnlySendsQueuedEvents(); void postedEventsPingPong(); void eventLoopExit(); + void interruptTrampling(); }; bool tst_QEventDispatcher::event(QEvent *e) @@ -421,5 +422,31 @@ void tst_QEventDispatcher::eventLoopExit() QVERIFY(!timeoutObserved); } +// Based on QTBUG-91539: In the event dispatcher on Windows we overwrite the +// interrupt once we start processing events (this pattern is also in the 'unix' dispatcher) +// which would lead the dispatcher to accidentally ignore certain interrupts and, +// as in the bug report, would not quit, leaving the thread alive and running. +void tst_QEventDispatcher::interruptTrampling() +{ + class WorkerThread : public QThread + { + void run() override { + auto dispatcher = eventDispatcher(); + QVERIFY(dispatcher); + dispatcher->processEvents(QEventLoop::AllEvents); + QTimer::singleShot(0, [dispatcher]() { + dispatcher->wakeUp(); + }); + dispatcher->processEvents(QEventLoop::WaitForMoreEvents); + dispatcher->interrupt(); + dispatcher->processEvents(QEventLoop::WaitForMoreEvents); + } + }; + WorkerThread thread; + thread.start(); + QVERIFY(thread.wait(1000)); + QVERIFY(thread.isFinished()); +} + QTEST_MAIN(tst_QEventDispatcher) #include "tst_qeventdispatcher.moc" -- cgit v1.2.3