VcsCommandDecorator: Don't leak future objects

Don't leak QFutureInterface<void> and QFutureWatcher<void>
in case VcsCommandDecorator was destroyed before
the task was finished.

Change-Id: Ib915afe29250f3e5c3fe2e1d465005a0c980252b
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2022-07-19 15:23:43 +02:00
parent 163625f56a
commit 715e304f93

View File

@@ -47,7 +47,7 @@
#include <QDebug> #include <QDebug>
#include <QFileInfo> #include <QFileInfo>
#include <QFutureWatcher> #include <QFutureInterface>
#include <QStringList> #include <QStringList>
#include <QTextCodec> #include <QTextCodec>
#include <QVariant> #include <QVariant>
@@ -81,12 +81,14 @@ class VcsCommandDecorator : public QObject
{ {
public: public:
VcsCommandDecorator(ShellCommand *command); VcsCommandDecorator(ShellCommand *command);
~VcsCommandDecorator();
private: private:
void addTask(const QFuture<void> &future); void addTask(const QFuture<void> &future);
void postRunCommand(const FilePath &workingDirectory); void postRunCommand(const FilePath &workingDirectory);
ShellCommand *m_command; ShellCommand *m_command;
QFutureInterface<void> m_futureInterface;
}; };
VcsCommandDecorator::VcsCommandDecorator(ShellCommand *command) VcsCommandDecorator::VcsCommandDecorator(ShellCommand *command)
@@ -121,7 +123,13 @@ VcsCommandDecorator::VcsCommandDecorator(ShellCommand *command)
connect(ICore::instance(), &ICore::coreAboutToClose, this, [this, connection] { connect(ICore::instance(), &ICore::coreAboutToClose, this, [this, connection] {
disconnect(connection); disconnect(connection);
m_command->abort(); m_command->abort();
});} });
}
VcsCommandDecorator::~VcsCommandDecorator()
{
m_futureInterface.reportFinished();
}
void VcsCommandDecorator::addTask(const QFuture<void> &future) void VcsCommandDecorator::addTask(const QFuture<void> &future)
{ {
@@ -133,18 +141,7 @@ void VcsCommandDecorator::addTask(const QFuture<void> &future)
if (m_command->hasProgressParser()) { if (m_command->hasProgressParser()) {
ProgressManager::addTask(future, name, id); ProgressManager::addTask(future, name, id);
} else { } else {
// add a timed tasked based on timeout ProgressManager::addTimedTask(m_futureInterface, name, id, qMax(2, m_command->timeoutS() / 5));
// we cannot access the future interface directly, so we need to create a new one
// with the same lifetime
auto fi = new QFutureInterface<void>();
auto watcher = new QFutureWatcher<void>();
connect(watcher, &QFutureWatcherBase::finished, [fi, watcher] {
fi->reportFinished();
delete fi;
watcher->deleteLater();
});
watcher->setFuture(future);
ProgressManager::addTimedTask(*fi, name, id, qMax(2, m_command->timeoutS() / 5));
} }
Internal::VcsPlugin::addFuture(future); Internal::VcsPlugin::addFuture(future);