diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp index 82c6a0b2f99..605e24252e7 100644 --- a/src/plugins/projectexplorer/extracompiler.cpp +++ b/src/plugins/projectexplorer/extracompiler.cpp @@ -375,6 +375,14 @@ ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const Utils:: ExtraCompiler(project, source, targets, parent) { } +ProcessExtraCompiler::~ProcessExtraCompiler() +{ + if (!m_watcher) + return; + m_watcher->cancel(); + m_watcher->waitForFinished(); +} + void ProcessExtraCompiler::run(const QByteArray &sourceContents) { ContentProvider contents = [this, sourceContents]() { return sourceContents; }; @@ -429,17 +437,18 @@ void ProcessExtraCompiler::runImpl(const ContentProvider &provider) buildEnvironment())); } -FileNameToContentsHash ProcessExtraCompiler::runInThread( +void ProcessExtraCompiler::runInThread( + QFutureInterface &futureInterface, const Utils::FileName &cmd, const Utils::FileName &workDir, const QStringList &args, const ContentProvider &provider, const Utils::Environment &env) { if (cmd.isEmpty() || !cmd.toFileInfo().isExecutable()) - return FileNameToContentsHash(); + return; const QByteArray sourceContents = provider(); if (sourceContents.isNull() || !prepareToRun(sourceContents)) - return FileNameToContentsHash(); + return; QProcess process; @@ -449,25 +458,38 @@ FileNameToContentsHash ProcessExtraCompiler::runInThread( process.start(cmd.toString(), args, QIODevice::ReadWrite); if (!process.waitForStarted()) { handleProcessError(&process); - return FileNameToContentsHash(); + return; + } + bool isCanceled = futureInterface.isCanceled(); + if (!isCanceled) { + handleProcessStarted(&process, sourceContents); + forever { + bool done = process.waitForFinished(200); + isCanceled = futureInterface.isCanceled(); + if (done || isCanceled) + break; + } } - handleProcessStarted(&process, sourceContents); - process.waitForFinished(); - if (process.state() == QProcess::Running) { + isCanceled |= process.state() == QProcess::Running; + if (isCanceled) { process.kill(); process.waitForFinished(3000); + return; } - return handleProcessFinished(&process); + futureInterface.reportResult(handleProcessFinished(&process)); } void ProcessExtraCompiler::cleanUp() { QTC_ASSERT(m_watcher, return); - const FileNameToContentsHash data = m_watcher->future().result(); + auto future = m_watcher->future(); delete m_watcher; m_watcher = nullptr; + if (!future.resultCount()) + return; + const FileNameToContentsHash data = future.result(); if (data.isEmpty()) return; // There was some kind of error... diff --git a/src/plugins/projectexplorer/extracompiler.h b/src/plugins/projectexplorer/extracompiler.h index 024c9b87584..21efd6b29f4 100644 --- a/src/plugins/projectexplorer/extracompiler.h +++ b/src/plugins/projectexplorer/extracompiler.h @@ -101,6 +101,7 @@ public: ProcessExtraCompiler(const Project *project, const Utils::FileName &source, const Utils::FileNameList &targets, QObject *parent = nullptr); + ~ProcessExtraCompiler(); protected: // This will run a process in a thread, if @@ -128,9 +129,10 @@ protected: private: using ContentProvider = std::function; void runImpl(const ContentProvider &sourceContents); - FileNameToContentsHash runInThread(const Utils::FileName &cmd, const Utils::FileName &workDir, - const QStringList &args, const ContentProvider &provider, - const Utils::Environment &env); + void runInThread(QFutureInterface &futureInterface, + const Utils::FileName &cmd, const Utils::FileName &workDir, + const QStringList &args, const ContentProvider &provider, + const Utils::Environment &env); void cleanUp(); QFutureWatcher *m_watcher = nullptr;