AbstractProcessStep: Do not crash when cancelling a build

Task-number: QTCREATORBUG-17591
Change-Id: I3d03b46ba1abbf11ba681d690647b3114fbb28a5
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Tobias Hunger
2017-01-16 12:26:27 +01:00
committed by Tim Jenssen
parent 6e13b7afbb
commit 4a26a2c283
2 changed files with 21 additions and 11 deletions

View File

@@ -212,11 +212,12 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi)
m_timer.start(); m_timer.start();
} }
void AbstractProcessStep::cleanUp() void AbstractProcessStep::cleanUp(QProcess *process)
{ {
// The process has finished, leftover data is read in processFinished // The process has finished, leftover data is read in processFinished
processFinished(m_process->exitCode(), m_process->exitStatus()); bool returnValue = false;
const bool returnValue = processSucceeded(m_process->exitCode(), m_process->exitStatus()) || m_ignoreReturnValue; processFinished(process->exitCode(), process->exitStatus());
returnValue = processSucceeded(process->exitCode(), process->exitStatus()) || m_ignoreReturnValue;
m_outputParserChain.reset(); m_outputParserChain.reset();
m_process.reset(); m_process.reset();
@@ -293,6 +294,8 @@ bool AbstractProcessStep::processSucceeded(int exitCode, QProcess::ExitStatus st
void AbstractProcessStep::processReadyReadStdOutput() void AbstractProcessStep::processReadyReadStdOutput()
{ {
if (!m_process)
return;
m_process->setReadChannel(QProcess::StandardOutput); m_process->setReadChannel(QProcess::StandardOutput);
while (m_process->canReadLine()) { while (m_process->canReadLine()) {
QString line = QString::fromLocal8Bit(m_process->readLine()); QString line = QString::fromLocal8Bit(m_process->readLine());
@@ -315,6 +318,8 @@ void AbstractProcessStep::stdOutput(const QString &line)
void AbstractProcessStep::processReadyReadStdError() void AbstractProcessStep::processReadyReadStdError()
{ {
if (!m_process)
return;
m_process->setReadChannel(QProcess::StandardError); m_process->setReadChannel(QProcess::StandardError);
while (m_process->canReadLine()) { while (m_process->canReadLine()) {
QString line = QString::fromLocal8Bit(m_process->readLine()); QString line = QString::fromLocal8Bit(m_process->readLine());
@@ -344,6 +349,7 @@ void AbstractProcessStep::checkForCancel()
{ {
if (m_futureInterface->isCanceled() && m_timer.isActive()) { if (m_futureInterface->isCanceled() && m_timer.isActive()) {
m_timer.stop(); m_timer.stop();
Core::Reaper::reap(m_process.release()); Core::Reaper::reap(m_process.release());
} }
} }
@@ -412,13 +418,17 @@ void AbstractProcessStep::slotProcessFinished(int, QProcess::ExitStatus)
{ {
m_timer.stop(); m_timer.stop();
const QString stdErrLine = QString::fromLocal8Bit(m_process->readAllStandardError()); QProcess *process = m_process.get();
if (!stdErrLine.isEmpty()) if (!process) // Happens when the process was canceled and handed over to the Reaper.
stdError(stdErrLine); process = qobject_cast<QProcess *>(sender()); // The process was canceled!
const QString stdoutLine = QString::fromLocal8Bit(m_process->readAllStandardOutput()); const QString stdErrLine = process ? QString::fromLocal8Bit(process->readAllStandardError()) : QString();
if (!stdoutLine.isEmpty()) for (const QString &l : stdErrLine.split('\n'))
stdOutput(stdoutLine); stdError(l);
cleanUp(); const QString stdOutLine = process ? QString::fromLocal8Bit(process->readAllStandardOutput()) : QString();
for (const QString &l : stdOutLine.split('\n'))
stdError(l);
cleanUp(process);
} }

View File

@@ -82,7 +82,7 @@ private:
void slotProcessFinished(int, QProcess::ExitStatus); void slotProcessFinished(int, QProcess::ExitStatus);
void checkForCancel(); void checkForCancel();
void cleanUp(); void cleanUp(QProcess *process);
void taskAdded(const Task &task, int linkedOutputLines = 0, int skipLines = 0); void taskAdded(const Task &task, int linkedOutputLines = 0, int skipLines = 0);