From 4cd8eeaf8c6a05f09bdbc92690b63f5233abdad0 Mon Sep 17 00:00:00 2001 From: Sona Kurazyan Date: Mon, 24 Jan 2022 15:57:07 +0100 Subject: [PATCH] Fix memory leak in QtConcurrent::run when called with a NULL QThreadPool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QThreadPool automatically deletes the runnable after it finishes running the task. In case QThreadPool is nullptr, we should delete the runnable manually. This amends 87b93c29be02f0a7ff9424b5e2b6431e20bd4c40. Pick-to: 6.3 6.2 5.15 Change-Id: Id7e4ed3d4d6de05990edf62e4099852983debc64 Reviewed-by: MÃ¥rten Nordheim --- src/concurrent/qtconcurrentrunbase.h | 1 + .../qtconcurrentrun/tst_qtconcurrentrun.cpp | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/concurrent/qtconcurrentrunbase.h b/src/concurrent/qtconcurrentrunbase.h index 48703621469..e21f6367009 100644 --- a/src/concurrent/qtconcurrentrunbase.h +++ b/src/concurrent/qtconcurrentrunbase.h @@ -99,6 +99,7 @@ public: } else { promise.reportCanceled(); promise.reportFinished(); + delete this; } return theFuture; } diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp index 0ff98c42f5b..ee137916523 100644 --- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp +++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp @@ -66,6 +66,7 @@ private slots: void customPromise(); void nonDefaultConstructibleValue(); void nullThreadPool(); + void nullThreadPoolNoLeak(); }; void light() @@ -1589,5 +1590,27 @@ void tst_QtConcurrentRun::nullThreadPool() QVERIFY(!isInvoked); } +struct LifetimeChecker +{ + LifetimeChecker() { ++count; } + LifetimeChecker(const LifetimeChecker &) { ++count; } + ~LifetimeChecker() { --count; } + + void operator()() { } + + static std::atomic count; +}; +std::atomic LifetimeChecker::count = 0; + +void tst_QtConcurrentRun::nullThreadPoolNoLeak() +{ + { + QThreadPool *pool = nullptr; + auto future = run(pool, LifetimeChecker()); + future.waitForFinished(); + } + QCOMPARE(LifetimeChecker::count, 0); +} + QTEST_MAIN(tst_QtConcurrentRun) #include "tst_qtconcurrentrun.moc"