From d6c592aa2f62edbd13baa7fbf9b19ea93b0994a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Mon, 14 Oct 2024 12:12:37 +0200 Subject: [PATCH] QThreadPool: fix regression with negative expiryTimeout It's supposed to indicate a thread never expires, but following a change where it stores the expiry with chrono we no longer considered a negative expiry as 'forever', but rather it immediately expires! More directly it is because we end up calling QDeadlineTimer::setPreciseRemainingTime(0 secs, X nsecs), and it only cares about negative seconds to set Forever. There are complications to consider nsecs for this since several nanoseconds may pass between initially calling the function and assigning the values... Amends 1f2a230b898af9da73463bca27b5883d36da7a91. Fixes: QTBUG-129898 Change-Id: I9626de31810fb2751ff6d83165d7dce5258a9baf Reviewed-by: Thiago Macieira (cherry picked from commit c57027199996d0f0d2ac8ebc4505c78afa54ab5a) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/thread/qthreadpool.cpp | 7 ++++++- .../thread/qthreadpool/tst_qthreadpool.cpp | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index f4dc940cc4b..3a9c0569e7c 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -113,7 +113,12 @@ void QThreadPoolThread::run() manager->waitingThreads.enqueue(this); registerThreadInactive(); // wait for work, exiting after the expiry timeout is reached - runnableReady.wait(locker.mutex(), QDeadlineTimer(manager->expiryTimeout)); + QDeadlineTimer deadline; + if (manager->expiryTimeout.count() < 0) + deadline = QDeadlineTimer::Forever; + else + deadline.setRemainingTime(manager->expiryTimeout); + runnableReady.wait(locker.mutex(), deadline); // this thread is about to be deleted, do not work or expire if (!manager->allThreads.contains(this)) { Q_ASSERT(manager->queue.isEmpty()); diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 2006016d478..6decea9b939 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -414,6 +414,21 @@ void tst_QThreadPool::expiryTimeout() threadPool.setExpiryTimeout(expiryTimeout); QCOMPARE(threadPool.expiryTimeout(), expiryTimeout); + + threadPool.waitForDone(); + // Negative times should be 'forever' + threadPool.setExpiryTimeout(-1); + QCOMPARE(threadPool.expiryTimeout(), -1); + + threadPool.start(&task); + QVERIFY(task.semaphore.tryAcquire(1, 10'000)); + QCOMPARE(task.runCount.loadRelaxed(), 3); + firstThread = task.thread; + + QTest::qWait(100); // Let some time elapse after the task finishes... + + // Since the thread never expires it should still be waiting for a new task: + QVERIFY(firstThread->isRunning()); } void tst_QThreadPool::expiryTimeoutRace() // QTBUG-3786