summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2024-10-14 12:12:37 +0200
committerMårten Nordheim <marten.nordheim@qt.io>2024-10-15 14:44:46 +0200
commitc57027199996d0f0d2ac8ebc4505c78afa54ab5a (patch)
treee60e7ea93dc0d3c519440353ef974719495dc0ee
parent7a6ecc3e5d4d55709508d6c93414b4af57575a4c (diff)
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 Pick-to: 6.8 Change-Id: I9626de31810fb2751ff6d83165d7dce5258a9baf Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/thread/qthreadpool.cpp7
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp15
2 files changed, 21 insertions, 1 deletions
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