diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-01 09:56:16 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-01 20:55:04 +0200 |
commit | a5e6c50ef45e9b75867e1730c510f5739b00f176 (patch) | |
tree | a4ae5121eebbffbe24c7be1316e90dc51aa3f31b /tests | |
parent | c9d2d93d0f800e0097e6b35d32a3bb251cf9070d (diff) |
Fix race condition in QThreadPool::clear
Since we drop the lock while deleting threads, we need to handle
the queue possibly being accessed and changed by the pool threads
while clear() is running.
Fixes: QTBUG-87092
Change-Id: I7611edab90520454278502a58621e299f9cd1f6e
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
(cherry picked from commit fe36d47b371b71ad5fec30d4b5d7bf0baa0205ea)
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 49ce918caf..cd245030db 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -93,6 +93,7 @@ private slots: void priorityStart(); void waitForDone(); void clear(); + void clearWithAutoDelete(); #if QT_DEPRECATED_SINCE(5, 9) void cancel(); #endif @@ -976,6 +977,31 @@ void tst_QThreadPool::clear() QCOMPARE(count.loadRelaxed(), threadPool.maxThreadCount()); } +void tst_QThreadPool::clearWithAutoDelete() +{ + class MyRunnable : public QRunnable + { + public: + MyRunnable() {} + void run() override { QThread::usleep(30); } + }; + + QThreadPool threadPool; + threadPool.setMaxThreadCount(4); + const int loopCount = 20; + const int batchSize = 500; + // Should not crash see QTBUG-87092 + for (int i = 0; i < loopCount; i++) { + threadPool.clear(); + for (int j = 0; j < batchSize; j++) { + auto *runnable = new MyRunnable(); + runnable->setAutoDelete(true); + threadPool.start(runnable); + } + } + QVERIFY(threadPool.waitForDone()); +} + #if QT_DEPRECATED_SINCE(5, 9) void tst_QThreadPool::cancel() { |