Fix a crash when modifying pro file

In some unlikely case it may happen that between finished() signal
is emitted by a watcher and when the queued handler is being called,
someone could have called CppProjectUpdater::cancel() and delete
the watcher immediately. In this case the handler could operate
on deleted watcher instance.

Add a QPointer in order to guard the watcher inside the queued
handler.

Amends: e3b639047f

Fixes: QTCREATORBUG-26507
Change-Id: Idb4a953e9017ce672adc64becb3061bd80c8c378
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Jarek Kobus
2021-11-01 13:18:43 +01:00
parent 38af447ee0
commit 6e8dcbcfd2

View File

@@ -93,11 +93,16 @@ void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo,
// extra compilers // extra compilers
for (QPointer<ExtraCompiler> compiler : qAsConst(m_extraCompilers)) { for (QPointer<ExtraCompiler> compiler : qAsConst(m_extraCompilers)) {
if (compiler->isDirty()) { if (compiler->isDirty()) {
auto watcher = new QFutureWatcher<void>; QPointer<QFutureWatcher<void>> watcher = new QFutureWatcher<void>;
// queued connection to delay after the extra compiler updated its result contents, // queued connection to delay after the extra compiler updated its result contents,
// which is also done in the main thread when compiler->run() finished // which is also done in the main thread when compiler->run() finished
connect(watcher, &QFutureWatcherBase::finished, connect(watcher, &QFutureWatcherBase::finished,
this, [this, watcher] { this, [this, watcher] {
// In very unlikely case the CppProjectUpdater::cancel() could have been
// invoked after posting the finished() signal and before this handler
// gets called. In this case the watcher is already deleted.
if (!watcher)
return;
m_projectUpdateFutureInterface->setProgressValue( m_projectUpdateFutureInterface->setProgressValue(
m_projectUpdateFutureInterface->progressValue() + 1); m_projectUpdateFutureInterface->progressValue() + 1);
m_extraCompilersFutureWatchers.remove(watcher); m_extraCompilersFutureWatchers.remove(watcher);