diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2017-02-10 11:29:38 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2017-02-15 11:25:48 +0000 |
commit | b4689401a5ea142c9e2136b77d9193792874400a (patch) | |
tree | 8c75e835ccf111f226aca4082d1510144ca52f15 /tests/auto/corelib | |
parent | 410a14cc768ad084a4e474ffd8b61471405fce0f (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>
Diffstat (limited to 'tests/auto/corelib')
-rw-r--r-- | tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp | 20 |
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 152aa4abdd..5b7242fddb 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -960,6 +960,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: @@ -995,6 +1010,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; |