diff options
author | Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io> | 2021-09-14 16:02:26 +0200 |
---|---|---|
committer | Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io> | 2021-09-18 15:59:27 +0200 |
commit | 14b0d9a50f1679daabb0f5a64368006f7a64a189 (patch) | |
tree | 8e6e311d2f049bd7b532803cc71b3b40a7adbee4 | |
parent | 0d6bbe6978714431f18aa6f797ffb978d054e002 (diff) |
QThreadPool: Fix restarting of expired threads
Ensure that expired threads have actually finished before attempting
to restart them. Calling start() on a thread that is not yet finished
does nothing.
Add a regression test into tst_qthreadpool that attempts to trigger
reuse of expired threads and verifies that all submitted tasks
execute.
Fixes: QTBUG-72872
Change-Id: I2109b628b8a4e91491115dc56aebf3eb249646b5
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
(cherry picked from commit 1afd562b0b0bbba02575aa79601f0fae555cfa19)
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 5 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp | 25 |
2 files changed, 30 insertions, 0 deletions
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index 14d7acffb2..282119a5c5 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -195,6 +195,11 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task) ++activeThreads; thread->runnable = task; + + // Ensure that the thread has actually finished, otherwise the following + // start() has no effect. + thread->wait(); + Q_ASSERT(thread->isFinished()); thread->start(); return true; } diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index bf313c27ef..e85fb5ea88 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -104,6 +104,7 @@ private slots: void stressTest(); void takeAllAndIncreaseMaxThreadCount(); void waitForDoneAfterTake(); + void threadReuse(); private: QMutex m_functionTestMutex; @@ -1385,5 +1386,29 @@ void tst_QThreadPool::waitForDoneAfterTake() } +/* + Try trigger reuse of expired threads and check that all tasks execute. + + This is a regression test for QTBUG-72872. +*/ +void tst_QThreadPool::threadReuse() +{ + QThreadPool manager; + manager.setExpiryTimeout(-1); + manager.setMaxThreadCount(1); + + constexpr int repeatCount = 10000; + constexpr int timeoutMs = 1000; + QSemaphore sem; + + for (int i = 0; i < repeatCount; i++) { + manager.start([&sem]() { sem.release(); }); + manager.start([&sem]() { sem.release(); }); + manager.releaseThread(); + QVERIFY(sem.tryAcquire(2, timeoutMs)); + manager.reserveThread(); + } +} + QTEST_MAIN(tst_QThreadPool); #include "tst_qthreadpool.moc" |