summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qfutureinterface.cpp
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2020-11-30 13:03:41 +0100
committerSona Kurazyan <sona.kurazyan@qt.io>2020-12-01 15:59:12 +0100
commit95cea24fa2f3eed5e7d8cfca085a6f09e7643331 (patch)
tree3107da8186cadf95a8eca592e04098412f4e3296 /src/corelib/thread/qfutureinterface.cpp
parentb5b2640a65de20d05890fa9e6462bb7b88f83964 (diff)
Fix memory leaks in QFuture's continuations
There were two issues: - Some of the continuations were allocating memory for the continuation's context dynamically, but deleting the allocated memory only if they were actually invoked. Since the continuations may not be invoked at all, this could cause memory leaks. Fixed by postponing the allocations to the point when the continuations need to be invoked. - In other cases the parent future is captured by copy in the continuation's lambda, which is then saved in the parent. This causes the following problem: the data of the ref-counted parent will be deleted as soon as its last copy gets deleted. But the saved continuation will prevent it from being deleted, since it holds a copy of parent. To break the circular dependency, instead of capturing the parent inside the lambda, we can pass the parent's data directly to continuation when calling it. Fixes: QTBUG-87289 Change-Id: If340520b68f6e960bc80953ca18b796173d34f7b Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io> (cherry picked from commit 5d26d40a5596be048be87f309df9264bac741be9) Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
Diffstat (limited to 'src/corelib/thread/qfutureinterface.cpp')
-rw-r--r--src/corelib/thread/qfutureinterface.cpp6
1 files changed, 3 insertions, 3 deletions
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index 57ddc7407e..7a8ba08103 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -744,14 +744,14 @@ void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState)
state.storeRelaxed(newState);
}
-void QFutureInterfaceBase::setContinuation(std::function<void()> func)
+void QFutureInterfaceBase::setContinuation(std::function<void(const QFutureInterfaceBase &)> func)
{
QMutexLocker lock(&d->continuationMutex);
// If the state is ready, run continuation immediately,
// otherwise save it for later.
if (isFinished()) {
lock.unlock();
- func();
+ func(*this);
} else {
d->continuation = std::move(func);
}
@@ -762,7 +762,7 @@ void QFutureInterfaceBase::runContinuation() const
QMutexLocker lock(&d->continuationMutex);
if (d->continuation) {
lock.unlock();
- d->continuation();
+ d->continuation(*this);
}
}