summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <[email protected]>2023-12-22 15:06:10 +0100
committerIvan Solovev <[email protected]>2024-01-08 18:29:26 +0100
commit936e72d18075b79c8d29353618dfbd052ae59dae (patch)
tree646a4f15bed717648ee990863a6993b8e3c4f351
parent8ce261f6d857e8b05c8043042fce101cb95cd868 (diff)
Fix QThreadPool::maxThreadCount() usage
The docs claim that QThreadPool always creates at least one thread. However, the user can (usually by mistake) request zero or a negative number of threads. The maxThreadCount() function is simply returning the value, that was requested by the user. Since it's a public API, it is used in several places in QtConcurrent, where it is assumed that the value is always positive. This can lead to a crash if the user sets zero as a maxThreadCount. Update all such places with std::max(maxThreadCount(), 1). Prefer this approach over changing the return value of maxThreadCount(), because its behavior is documented and tested. Amends 885eff053797d56f2e295558d0a71b030fbb1a69. Fixes: QTBUG-120335 Pick-to: 6.7 6.6 6.5 6.2 Change-Id: Id3b2087cec7fbc7a2d42febca6586f2dacffe444 Reviewed-by: Thiago Macieira <[email protected]>
-rw-r--r--src/concurrent/qtconcurrentiteratekernel.cpp2
-rw-r--r--src/concurrent/qtconcurrentreducekernel.h2
-rw-r--r--src/network/kernel/qhostinfo.cpp2
-rw-r--r--tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp22
4 files changed, 25 insertions, 3 deletions
diff --git a/src/concurrent/qtconcurrentiteratekernel.cpp b/src/concurrent/qtconcurrentiteratekernel.cpp
index 088c8384ced..00228f181cb 100644
--- a/src/concurrent/qtconcurrentiteratekernel.cpp
+++ b/src/concurrent/qtconcurrentiteratekernel.cpp
@@ -67,7 +67,7 @@ namespace QtConcurrent {
*/
BlockSizeManager::BlockSizeManager(QThreadPool *pool, int iterationCount)
- : maxBlockSize(iterationCount / (pool->maxThreadCount() * 2)),
+ : maxBlockSize(iterationCount / (std::max(pool->maxThreadCount(), 1) * 2)),
beforeUser(0), afterUser(0),
m_blockSize(1)
{ }
diff --git a/src/concurrent/qtconcurrentreducekernel.h b/src/concurrent/qtconcurrentreducekernel.h
index cb7d7910aad..c337a9192fc 100644
--- a/src/concurrent/qtconcurrentreducekernel.h
+++ b/src/concurrent/qtconcurrentreducekernel.h
@@ -117,7 +117,7 @@ class ReduceKernel
public:
ReduceKernel(QThreadPool *pool, ReduceOptions _reduceOptions)
: reduceOptions(_reduceOptions), progress(0), resultsMapSize(0),
- threadCount(pool->maxThreadCount())
+ threadCount(std::max(pool->maxThreadCount(), 1))
{ }
void runReduce(ReduceFunctor &reduce,
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index 9e4a3fae83c..99ed32b8034 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -964,7 +964,7 @@ void QHostInfoLookupManager::rescheduleWithMutexHeld()
isAlreadyRunning).second,
scheduledLookups.end());
- const int availableThreads = threadPool.maxThreadCount() - currentLookups.size();
+ const int availableThreads = std::max(threadPool.maxThreadCount(), 1) - currentLookups.size();
if (availableThreads > 0) {
int readyToStartCount = qMin(availableThreads, scheduledLookups.size());
auto it = scheduledLookups.begin();
diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
index 94248404da4..e66edb1b602 100644
--- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
+++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
@@ -185,6 +185,17 @@ void tst_QtConcurrentMap::map()
QCOMPARE(list, NonTemplateSequence({ 2, 4, 6 }));
}
+ // custom pool with invalid number of threads
+ {
+ QList<int> list;
+ list << 1 << 2 << 3;
+ QThreadPool pool;
+ pool.setMaxThreadCount(0); // explicitly set incorrect value
+ // This should not crash
+ QtConcurrent::map(&pool, list, MultiplyBy2InPlace()).waitForFinished();
+ QCOMPARE(list, QList<int>() << 2 << 4 << 6);
+ }
+
#if 0
// not allowed: map() with immutable sequences makes no sense
{
@@ -1075,6 +1086,17 @@ void tst_QtConcurrentMap::mappedReducedThreadPool()
intCube, intSumReduce);
QCOMPARE(result, sumOfCubes);
}
+
+ {
+ // pool with invalid number of threads
+ QThreadPool pool;
+ pool.setMaxThreadCount(0); // explicitly set incorrect value
+
+ // This should not crash
+ NonTemplateSequence list { 1, 2, 3 };
+ auto future = QtConcurrent::mappedReduced(&pool, list, multiplyBy2, intSumReduce);
+ QCOMPARE(future.result(), 12);
+ }
}
void tst_QtConcurrentMap::mappedReducedWithMoveOnlyCallable()