summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIevgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>2021-09-14 16:02:26 +0200
committerIevgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>2021-09-18 15:59:27 +0200
commit14b0d9a50f1679daabb0f5a64368006f7a64a189 (patch)
tree8e6e311d2f049bd7b532803cc71b3b40a7adbee4
parent0d6bbe6978714431f18aa6f797ffb978d054e002 (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.cpp5
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp25
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"