forked from qt-creator/qt-creator
Fix a deadlock when closing Creator while loading a project
Replace the call to SynchronousProcess::run() by asynchronous call that invokes a process. This change may be tested by applying the additional patch mentioned in QTCREATORBUG-25385 description. Don't call the SynchronousProcess::run() from the main thread when the Quit event was already scheduled for qApp, since the Quit event will get removed from the awaiting queue by a call to QEventLoop::exec(). Fixes: QTCREATORBUG-25385 Change-Id: I8af39552443bfa9b3af6e31ddce85a01b91bbbd8 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -39,6 +39,7 @@
|
|||||||
#include <android/androidconstants.h>
|
#include <android/androidconstants.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
|
#include <coreplugin/reaper.h>
|
||||||
#include <cpptools/cppprojectupdater.h>
|
#include <cpptools/cppprojectupdater.h>
|
||||||
#include <cpptools/cpptoolsconstants.h>
|
#include <cpptools/cpptoolsconstants.h>
|
||||||
#include <cpptools/generatedcodemodelsupport.h>
|
#include <cpptools/generatedcodemodelsupport.h>
|
||||||
@@ -59,6 +60,7 @@
|
|||||||
#include <utils/macroexpander.h>
|
#include <utils/macroexpander.h>
|
||||||
#include <utils/mimetypes/mimetype.h>
|
#include <utils/mimetypes/mimetype.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/runextensions.h>
|
||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -207,6 +209,7 @@ CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc)
|
|||||||
|
|
||||||
CMakeBuildSystem::~CMakeBuildSystem()
|
CMakeBuildSystem::~CMakeBuildSystem()
|
||||||
{
|
{
|
||||||
|
m_futureSynchronizer.waitForFinished();
|
||||||
if (!m_treeScanner.isFinished()) {
|
if (!m_treeScanner.isFinished()) {
|
||||||
auto future = m_treeScanner.future();
|
auto future = m_treeScanner.future();
|
||||||
future.cancel();
|
future.cancel();
|
||||||
@@ -576,7 +579,7 @@ void CMakeBuildSystem::combineScanAndParse()
|
|||||||
|
|
||||||
emitBuildSystemUpdated();
|
emitBuildSystemUpdated();
|
||||||
|
|
||||||
QTimer::singleShot(0, this, &CMakeBuildSystem::runCTest);
|
runCTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeBuildSystem::checkAndReportError(QString &errorMessage)
|
void CMakeBuildSystem::checkAndReportError(QString &errorMessage)
|
||||||
@@ -921,19 +924,38 @@ void CMakeBuildSystem::runCTest()
|
|||||||
}
|
}
|
||||||
qCDebug(cmakeBuildSystemLog) << "Requesting ctest run after cmake run";
|
qCDebug(cmakeBuildSystemLog) << "Requesting ctest run after cmake run";
|
||||||
|
|
||||||
BuildDirParameters parameters(cmakeBuildConfiguration());
|
const BuildDirParameters parameters(cmakeBuildConfiguration());
|
||||||
QTC_ASSERT(parameters.isValid(), return);
|
QTC_ASSERT(parameters.isValid(), return);
|
||||||
|
|
||||||
FilePath workingDirectory = workDirectory(parameters);
|
const CommandLine cmd { m_ctestPath, { "-N", "--show-only=json-v1" } };
|
||||||
CommandLine cmd{m_ctestPath, {"-N", "--show-only=json-v1"}};
|
const QString workingDirectory = workDirectory(parameters).toString();
|
||||||
SynchronousProcess ctest;
|
const QStringList environment = cmakeBuildConfiguration()->environment().toStringList();
|
||||||
ctest.setTimeoutS(1);
|
|
||||||
ctest.setEnvironment(cmakeBuildConfiguration()->environment().toStringList());
|
|
||||||
ctest.setWorkingDirectory(workingDirectory.toString());
|
|
||||||
|
|
||||||
const SynchronousProcessResponse response = ctest.run(cmd);
|
auto future = Utils::runAsync([cmd, workingDirectory, environment]
|
||||||
if (response.result == SynchronousProcessResponse::Finished) {
|
(QFutureInterface<QByteArray> &futureInterface) {
|
||||||
const QJsonDocument json = QJsonDocument::fromJson(response.allRawOutput());
|
QProcess process;
|
||||||
|
process.setEnvironment(environment);
|
||||||
|
process.setWorkingDirectory(workingDirectory);
|
||||||
|
process.start(cmd.executable().toString(), cmd.splitArguments(), QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
if (!process.waitForStarted(1000) || !process.waitForFinished(1000)) {
|
||||||
|
if (process.state() == QProcess::NotRunning)
|
||||||
|
return;
|
||||||
|
process.terminate();
|
||||||
|
if (process.waitForFinished(1000))
|
||||||
|
return;
|
||||||
|
process.kill();
|
||||||
|
process.waitForFinished(1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (process.exitCode() || process.exitStatus() != QProcess::NormalExit)
|
||||||
|
return;
|
||||||
|
futureInterface.reportResult(process.readAllStandardOutput());
|
||||||
|
});
|
||||||
|
|
||||||
|
Utils::onFinished(future, this, [this](const QFuture<QByteArray> &future) {
|
||||||
|
if (future.resultCount()) {
|
||||||
|
const QJsonDocument json = QJsonDocument::fromJson(future.result());
|
||||||
if (!json.isEmpty() && json.isObject()) {
|
if (!json.isEmpty() && json.isObject()) {
|
||||||
const QJsonObject jsonObj = json.object();
|
const QJsonObject jsonObj = json.object();
|
||||||
const QJsonObject btGraph = jsonObj.value("backtraceGraph").toObject();
|
const QJsonObject btGraph = jsonObj.value("backtraceGraph").toObject();
|
||||||
@@ -950,13 +972,14 @@ void CMakeBuildSystem::runCTest()
|
|||||||
int line = btRef.value("line").toInt(-1);
|
int line = btRef.value("line").toInt(-1);
|
||||||
QTC_ASSERT(file != -1 && line != -1, continue);
|
QTC_ASSERT(file != -1 && line != -1, continue);
|
||||||
m_testNames.append({ test.value("name").toString(),
|
m_testNames.append({ test.value("name").toString(),
|
||||||
FilePath::fromString(cmakelists.at(file).toString()),
|
FilePath::fromString(cmakelists.at(file).toString()), line });
|
||||||
line
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit testInformationUpdated();
|
emit testInformationUpdated();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_futureSynchronizer.addFuture(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMakeBuildConfiguration *CMakeBuildSystem::cmakeBuildConfiguration() const
|
CMakeBuildConfiguration *CMakeBuildSystem::cmakeBuildConfiguration() const
|
||||||
|
@@ -35,6 +35,8 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/temporarydirectory.h>
|
#include <utils/temporarydirectory.h>
|
||||||
|
|
||||||
|
#include <QFutureSynchronizer>
|
||||||
|
|
||||||
namespace ProjectExplorer { class ExtraCompiler; }
|
namespace ProjectExplorer { class ExtraCompiler; }
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
@@ -181,6 +183,7 @@ private:
|
|||||||
// CTest integration
|
// CTest integration
|
||||||
QString m_ctestPath;
|
QString m_ctestPath;
|
||||||
QList<ProjectExplorer::TestCaseInfo> m_testNames;
|
QList<ProjectExplorer::TestCaseInfo> m_testNames;
|
||||||
|
QFutureSynchronizer<QByteArray> m_futureSynchronizer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user