summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2017-02-10 11:29:38 +0100
committerMarc Mutz <marc.mutz@kdab.com>2017-02-15 17:02:47 +0000
commit1088539c1d1ff592050ee732efd53da0bc33d4d0 (patch)
tree9c71db4921d776c267d4756c00572fbfef81c584 /tests
parentdca21964bec79a4415b406526a38c59ab4c56798 (diff)
tst_QThreadPool: don't deadlock when a cancel() test fails
We keep the runnables from finishing by having them block on a QSemaphore::acquire() call inside run(). If we fail a test that precedes the call to sem.release() further into the test, the early return will cause the thread pool to be destroyed, which will then attempt to wait for the runnables to finished, which, in turn wait for the semaphore to be released. -> dead lock Fix by introducing a RAII object to release the semaphore with a sufficiently large number to unblock all runnables. That number will in some situations be too large, but that does not matter. Change-Id: I1ec7e29b37bc36309e93e6e30708cc7db3c9579c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit b4689401a5ea142c9e2136b77d9193792874400a)
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp20
1 files changed, 20 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
index 5516ee2029..32910d37f8 100644
--- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
+++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
@@ -964,6 +964,21 @@ void tst_QThreadPool::cancel()
QSemaphore sem(0);
QSemaphore startedThreads(0);
+ class SemaphoreReleaser
+ {
+ QSemaphore &sem;
+ int n;
+ Q_DISABLE_COPY(SemaphoreReleaser)
+ public:
+ explicit SemaphoreReleaser(QSemaphore &sem, int n)
+ : sem(sem), n(n) {}
+
+ ~SemaphoreReleaser()
+ {
+ sem.release(n);
+ }
+ };
+
class BlockingRunnable : public QRunnable
{
public:
@@ -999,6 +1014,11 @@ void tst_QThreadPool::cancel()
QThreadPool threadPool;
threadPool.setMaxThreadCount(MaxThreadCount);
BlockingRunnable *runnables[runs];
+
+ // ensure that the QThreadPool doesn't deadlock if any of the checks fail
+ // and cause an early return:
+ const SemaphoreReleaser semReleaser(sem, runs);
+
count.store(0);
QAtomicInt dtorCounter = 0;
QAtomicInt runCounter = 0;