This is an automated email from the git hooks/post-receive script.

guix_mirror_bot pushed a commit to branch master
in repository guix.

The following commit(s) were added to refs/heads/master by this push:
     new e7a87d59b8 gnu: qtbase: Backport fix for flaky test.
e7a87d59b8 is described below

commit e7a87d59b84f20307f22f6878b39e0210496104e
Author: Brennan Vincent <[email protected]>
AuthorDate: Mon Jul 21 14:23:43 2025 -0700

    gnu: qtbase: Backport fix for flaky test.
    
    * gnu/packages/qt.scm (qtbase)[#:phases]: Add 'patch-aarch64-tests, which
    backports an upstream commit improving a flaky test.
    * gnu/packages/patches/qtbase-fix-thread-test.patch: New file.
    * gnu/local.mk (dist_patch_DATA): Register patch.
    
    Change-Id: Ibf9b95d7225ed42c9edad03a550d1c6e6f86be54
---
 gnu/local.mk                                      |   1 +
 gnu/packages/patches/qtbase-fix-thread-test.patch | 154 ++++++++++++++++++++++
 gnu/packages/qt.scm                               |  10 ++
 3 files changed, 165 insertions(+)

diff --git a/gnu/local.mk b/gnu/local.mk
index 46a483c15e..6e4664ac35 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -2205,6 +2205,7 @@ dist_patch_DATA =                                         
\
   %D%/packages/patches/qemu-fix-agent-paths.patch              \
   %D%/packages/patches/qrcodegen-cpp-cmake.patch               \
   %D%/packages/patches/qtbase-absolute-runpath.patch           \
+  %D%/packages/patches/qtbase-fix-thread-test.patch             \
   %D%/packages/patches/qtbase-qmake-fix-includedir.patch       \
   %D%/packages/patches/qtbase-qmlimportscanner-qml-import-path.patch   \
   %D%/packages/patches/qtbase-moc-ignore-gcc-macro.patch       \
diff --git a/gnu/packages/patches/qtbase-fix-thread-test.patch 
b/gnu/packages/patches/qtbase-fix-thread-test.patch
new file mode 100644
index 0000000000..d54386ccc7
--- /dev/null
+++ b/gnu/packages/patches/qtbase-fix-thread-test.patch
@@ -0,0 +1,154 @@
+From 2bce75a6b53cccbf9c813581b64eea87f3ab55fc Mon Sep 17 00:00:00 2001
+From: Thiago Macieira <[email protected]>
+Date: Fri, 1 Nov 2024 11:59:10 -0700
+Subject: [PATCH] tst_QThread: improve test on multiple threads waiting on
+ wait()
+
+Amends commit 5b5297fe87859f59a7aaf5e86a8915c00714fefa to make it more
+reliable against CI timeouts and flakiness. Now, we wait for the threads
+that are expected to timeout to actually timeout before releasing the
+target thread they were waiting on. It should be impossible now for this
+to go wrong. There should also be no problem of their handing off to a
+thread that will wait forever.
+
+I've added two more tests that could, possibly, have a problem in the
+CI: when timing-out threads hand off to a timed wait that is expected to
+succeed (the > 1s wait cases). Though this should be a rare occurrence,
+if ever: the target thread's runtime is the longest of the timing out
+threads' wait, plus 5 ms. That is 30 ms in the examples I wrote, so the
+additional extra time they're waiting on should be more than enough.
+
+An extra benefit is that this test now runs much faster, at 10 to 60 ms
+per test row, instead of 800 ms previously. The drawback is that a
+failure condition is likely going to be noticed by the QSemaphores
+deadlocking.
+
+Change-Id: I360d7e9c7accc1216291fffd743c88a362cf66ac
+Reviewed-by: Fabian Kosmale <[email protected]>
+---
+ .../corelib/thread/qthread/tst_qthread.cpp    | 63 +++++++++++++------
+ 1 file changed, 43 insertions(+), 20 deletions(-)
+
+diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp 
b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+index 99602098fac..beb843b0d8c 100644
+--- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp
++++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+@@ -36,6 +36,8 @@
+ #include <exception>
+ #endif
+ 
++#include <thread>
++
+ #include <QtTest/private/qemulationdetector_p.h>
+ 
+ using namespace std::chrono_literals;
+@@ -1226,21 +1228,28 @@ void tst_QThread::multiThreadWait_data()
+     // this is probably too fast and the Forever gets in too quickly
+     addRow(0, -1);
+ 
+-    addRow(100, -1);
+-    addRow(100, 200, -1);
+-    addRow(200, 100, -1);
+-    addRow(-1, 100, 100, 100);
++    // any time below 100ms (see below) is expected to timeout
++    addRow(25, -1);
++    addRow(25, 50, -1);
++    addRow(50, 25, -1);
++    addRow(-1, 25, 25, 25);
++    addRow(25, 2000);
++    addRow(25, 2000, 25, -1);
+ }
+ 
+ void tst_QThread::multiThreadWait()
+ {
++    static constexpr auto TimeoutThreshold = 100ms;
++    auto isExpectedToTimeout = [](unsigned value) {
++        return value < TimeoutThreshold.count();
++    };
++
+     class TargetThread : public QThread {
+     public:
+         QSemaphore sync;
+         void run() override
+         {
+             sync.acquire();
+-            msleep(Waiting_Thread::WaitTime);
+         }
+     };
+ 
+@@ -1265,43 +1274,57 @@ void tst_QThread::multiThreadWait()
+     QFETCH(QList<int>, deadlines);
+     TargetThread target;
+     target.start();
++    QElapsedTimer elapsedTimer;
++    elapsedTimer.start();
+ 
+-    QSemaphore startSema, endSema;
++    // we use a QSemaphore to wait on the WaiterThread::run() instead of
++    // QThread::wait() so it's easier to debug when the latter has a problem
++    QSemaphore startSema, timeoutSema, successSema;
+     std::array<std::unique_ptr<WaiterThread>, 5> threads;   // 5 threads is 
enough
++    int expectedTimeoutCount = 0;
+     for (int i = 0; i < deadlines.size(); ++i) {
+         threads[i] = std::make_unique<WaiterThread>();
+         threads[i]->startSema = &startSema;
+-        threads[i]->endSema = &endSema;
++        if (isExpectedToTimeout(deadlines.at(i))) {
++            ++expectedTimeoutCount;
++            threads[i]->endSema = &timeoutSema;
++        } else {
++            threads[i]->endSema = &successSema;
++        }
+         threads[i]->target = &target;
+         threads[i]->deadline = QDeadlineTimer(deadlines.at(i));
+         threads[i]->start();
+     }
+ 
+-    // release the waiting threads first, then the target thread they're 
waiting on
++    // release the waiting threads first, so they begin waiting
+     startSema.release(deadlines.size());
+-    target.sync.release();
+ 
+-    // wait for our waiting threads on a semaphore instead of QThread::wait()
+-    // to make debugging easier
+-    QVERIFY(endSema.tryAcquire(deadlines.size(), QDeadlineTimer::Forever));
++    // then wait for the threads that are expected to timeout to do so
++    QVERIFY(timeoutSema.tryAcquire(expectedTimeoutCount, 
QDeadlineTimer::Forever));
++
++    // compute the elapsed time for timing comparisons
++    std::this_thread::sleep_for(5ms);   // short, but long enough to avoid 
rounding errors
++    auto elapsed = elapsedTimer.durationElapsed();
++    std::this_thread::sleep_for(5ms);
++
++    // cause the target thread to exit, so the successful threads do succeed
++    target.sync.release();
++    int expectedSuccessCount = deadlines.size() - expectedTimeoutCount;
++    QVERIFY(successSema.tryAcquire(expectedSuccessCount, 
QDeadlineTimer::Forever));
+ 
+     // wait for all the threads to end, before QVERIFY/QCOMPAREs
+     for (int i = 0; i < deadlines.size(); ++i)
+         threads[i]->wait();
+     target.wait();
+ 
+-    std::chrono::milliseconds expectedDuration{Waiting_Thread::WaitTime};
+     for (int i = 0; i < deadlines.size(); ++i) {
+         auto printI = qScopeGuard([i] { qWarning("i = %i", i); });
+-        if (unsigned(deadlines.at(i)) < Waiting_Thread::WaitTime / 2) {
++        if (isExpectedToTimeout(deadlines.at(i))) {
++            QCOMPARE_LT(threads[i]->waitedDuration, elapsed);
+             QCOMPARE(threads[i]->result, false);
+-            QCOMPARE_LT(threads[i]->waitedDuration, expectedDuration);
+-        } else if (unsigned(deadlines.at(i)) > Waiting_Thread::WaitTime * 3 / 
2) {
+-            QCOMPARE(threads[i]->result, true);
+-            QCOMPARE_GE(threads[i]->waitedDuration, expectedDuration);
+         } else {
+-            qWarning("Wait time %i (index %i) is too close to the target 
time; test would be flaky",
+-                     deadlines.at(i), i);
++            QCOMPARE_GE(threads[i]->waitedDuration, elapsed);
++            QCOMPARE(threads[i]->result, true);
+         }
+         printI.dismiss();
+         threads[i].reset();
+-- 
+2.50.1
+
diff --git a/gnu/packages/qt.scm b/gnu/packages/qt.scm
index 69e3c04e94..45ab7f0300 100644
--- a/gnu/packages/qt.scm
+++ b/gnu/packages/qt.scm
@@ -901,6 +901,16 @@ tst_qt_cmake_create.cpp"
                     "dirs.append(\""
                     #$(this-package-input "shared-mime-info") "/share/mime"
                     "\");\n" all)))))
+            #$@(if (target-aarch64?)
+                   ;; backport of 2bce75a6b53cccbf9c813581b64eea87f3ab55fc,
+                   ;; which makes flaky tst_qthread less flaky.
+                   #~((add-after 'patch-more-paths 'patch-aarch64-tests
+                      (lambda _
+                        (invoke
+                         "patch" "-p1" "-i"
+                         #$(local-file
+                            (search-patch "qtbase-fix-thread-test.patch"))))))
+                 #~())
             (delete 'do-not-capture-python) ;move after patch-source-shebangs
             (add-after 'patch-source-shebangs 'do-not-capture-python
               (lambda _

Reply via email to