From dfcd5734278e9e9fc48f4784465cfa4b85dcef4b Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 24 Nov 2017 13:32:20 +0100 Subject: [PATCH] Qmake: Do not crash when closing a project while it is parsing * Fix crashes and resource leaks in qmake project. Task-number: QTCREATORBUG-19358 Change-Id: I3b383640cdf994b4014ccbfc4278be48f9e5fd3f Reviewed-by: Orgad Shaneh --- .../qmakeprojectmanager/qmakeparsernodes.cpp | 12 ++++++++--- .../qmakeprojectmanager/qmakeproject.cpp | 20 +++++++++++++------ .../qmakeprojectmanager/qmakeproject.h | 2 +- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp index 74faaf0cb06..8cda1a64233 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp @@ -1087,9 +1087,12 @@ QmakeProFile::QmakeProFile(QmakeProject *project, const FileName &filePath) : QmakeProFile::~QmakeProFile() { qDeleteAll(m_extraCompilers); + m_parseFutureWatcher.cancel(); m_parseFutureWatcher.waitForFinished(); if (m_readerExact) applyAsyncEvaluate(); + + cleanupProFileReaders(); } bool QmakeProFile::isParent(QmakeProFile *node) @@ -1489,7 +1492,8 @@ void QmakeProFile::asyncEvaluate(QFutureInterface &fi, QmakeE void QmakeProFile::applyAsyncEvaluate() { - applyEvaluate(m_parseFutureWatcher.result()); + if (m_parseFutureWatcher.isFinished()) + applyEvaluate(m_parseFutureWatcher.result()); m_project->decrementPendingEvaluateFutures(); } @@ -1625,8 +1629,10 @@ void QmakeProFile::applyEvaluate(QmakeEvalResult *evalResult) void QmakeProFile::cleanupProFileReaders() { - m_project->destroyProFileReader(m_readerExact); - m_project->destroyProFileReader(m_readerCumulative); + if (m_readerExact) + m_project->destroyProFileReader(m_readerExact); + if (m_readerCumulative) + m_project->destroyProFileReader(m_readerCumulative); m_readerExact = nullptr; m_readerCumulative = nullptr; diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index b8e9ffb77f9..8124b9d98cf 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -202,6 +202,12 @@ QmakeProject::~QmakeProject() m_cancelEvaluate = true; Q_ASSERT(m_qmakeGlobalsRefCnt == 0); delete m_qmakeVfs; + + if (m_asyncUpdateFutureInterface) { + m_asyncUpdateFutureInterface->reportCanceled(); + m_asyncUpdateFutureInterface->reportFinished(); + delete m_asyncUpdateFutureInterface; + } } QmakeProFile *QmakeProject::rootProFile() const @@ -508,6 +514,9 @@ void QmakeProject::decrementPendingEvaluateFutures() { --m_pendingEvaluateFuturesCount; + if (!rootProFile()) + return; // We are closing the project! + m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + 1); if (m_pendingEvaluateFuturesCount == 0) { // We are done! @@ -640,7 +649,7 @@ void QmakeProject::proFileParseError(const QString &errorMessage) QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile *qmakeProFile) { if (!m_qmakeGlobals) { - m_qmakeGlobals = new QMakeGlobals; + m_qmakeGlobals = std::make_unique(); m_qmakeGlobalsRefCnt = 0; Kit *k = KitManager::defaultKit(); @@ -664,7 +673,7 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile * if (qtVersion && qtVersion->isValid()) { m_qmakeGlobals->qmake_abslocation = QDir::cleanPath(qtVersion->qmakeCommand().toString()); - qtVersion->applyProperties(m_qmakeGlobals); + qtVersion->applyProperties(m_qmakeGlobals.get()); } m_qmakeGlobals->setDirectories(rootProFile()->sourceDir().toString(), rootProFile()->buildDir().toString()); @@ -693,7 +702,7 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile * } ++m_qmakeGlobalsRefCnt; - auto reader = new QtSupport::ProFileReader(m_qmakeGlobals, m_qmakeVfs); + auto reader = new QtSupport::ProFileReader(m_qmakeGlobals.get(), m_qmakeVfs); reader->setOutputDir(qmakeProFile->buildDir().toString()); @@ -702,7 +711,7 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile * QMakeGlobals *QmakeProject::qmakeGlobals() { - return m_qmakeGlobals; + return m_qmakeGlobals.get(); } QMakeVfs *QmakeProject::qmakeVfs() @@ -725,8 +734,7 @@ void QmakeProject::destroyProFileReader(QtSupport::ProFileReader *reader) QtSupport::ProFileCacheManager::instance()->discardFiles(dir); QtSupport::ProFileCacheManager::instance()->decRefCount(); - delete m_qmakeGlobals; - m_qmakeGlobals = nullptr; + m_qmakeGlobals.reset(); } } diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h index 717c11951bf..8ded09a1851 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.h +++ b/src/plugins/qmakeprojectmanager/qmakeproject.h @@ -184,7 +184,7 @@ private: QMakeVfs *m_qmakeVfs = nullptr; // cached data during project rescan - QMakeGlobals *m_qmakeGlobals = nullptr; + std::unique_ptr m_qmakeGlobals; int m_qmakeGlobalsRefCnt = 0; QString m_qmakeSysroot;