From 0556eec9b713a6613d400c64c6043e761827c716 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 26 Oct 2021 11:10:06 +0200 Subject: [PATCH] Use a new enum indicating various start failures Before the m_startFailure flag was used to detect the case when the process failed to start because of wrong filename. As this flag was set on any possible error we have always detected the wrong filename case. Replace this flag with a new enum describing various start failures. Don't report again the crashed message. Check if we have already reported the stop and we don't report it again. The processExited() handler is being called twice: directly from localGuiProcessError() and through the delayed localProcessDone(). Fixes: QTCREATORBUG-26467 Change-Id: I3cc6aa0c0b702256cefd77ba95793cd31e82ae10 Reviewed-by: hjk --- src/libs/utils/qtcprocess.cpp | 26 +++++++++++++--------- src/plugins/projectexplorer/runcontrol.cpp | 15 +++++-------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 0975b3fe220..810f770e0e3 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -475,6 +475,12 @@ static ProcessInterface *newProcessInstance(QObject *parent, QtcProcess::Process class QtcProcessPrivate : public QObject { public: + enum StartFailure { + NoFailure, + WrongFileNameFailure, + OtherFailure + }; + explicit QtcProcessPrivate(QtcProcess *parent, QtcProcess::ProcessImpl processImpl, ProcessMode processMode) @@ -488,7 +494,7 @@ public: connect(m_process, &ProcessInterface::finished, this, &QtcProcessPrivate::slotFinished); connect(m_process, &ProcessInterface::errorOccurred, - this, &QtcProcessPrivate::slotError); + this, [this](QProcess::ProcessError error) { handleError(error, OtherFailure); }); connect(m_process, &ProcessInterface::readyReadStandardOutput, this, &QtcProcessPrivate::handleReadyReadStandardOutput); connect(m_process, &ProcessInterface::readyReadStandardError, @@ -528,7 +534,7 @@ public: } else { m_process->setErrorString(QLatin1String( "The program \"%1\" does not exist or is not executable.").arg(program)); - slotError(QProcess::FailedToStart); + handleError(QProcess::FailedToStart, WrongFileNameFailure); } } @@ -544,7 +550,7 @@ public: void slotTimeout(); void slotFinished(int exitCode, QProcess::ExitStatus e); - void slotError(QProcess::ProcessError); + void handleError(QProcess::ProcessError error, StartFailure startFailure); void clearForRun(); QtcProcess::Result interpretExitCode(int exitCode); @@ -559,7 +565,7 @@ public: int m_hangTimerCount = 0; int m_maxHangTimerCount = defaultMaxHangTimerCount; - bool m_startFailure = false; + StartFailure m_startFailure = NoFailure; bool m_timeOutMessageBoxEnabled = false; bool m_waitingForUser = false; bool m_processUserEvents = false; @@ -573,7 +579,7 @@ void QtcProcessPrivate::clearForRun() m_stdErr.clearForRun(); m_stdErr.codec = m_codec; m_result = QtcProcess::StartFailed; - m_startFailure = false; + m_startFailure = NoFailure; } QtcProcess::Result QtcProcessPrivate::interpretExitCode(int exitCode) @@ -960,7 +966,7 @@ void QtcProcess::setResult(Result result) int QtcProcess::exitCode() const { - if (d->m_startFailure) + if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure) return 255; // This code is being returned by QProcess when FailedToStart error occurred return d->m_process->exitCode(); } @@ -1062,7 +1068,7 @@ void QtcProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) QProcess::ProcessError QtcProcess::error() const { - if (d->m_startFailure) + if (d->m_startFailure == QtcProcessPrivate::WrongFileNameFailure) return QProcess::FailedToStart; return d->m_process->error(); } @@ -1404,7 +1410,7 @@ void QtcProcess::runBlocking() // On Windows, start failure is triggered immediately if the // executable cannot be found in the path. Do not start the // event loop in that case. - if (!d->m_startFailure) { + if (d->m_startFailure == QtcProcessPrivate::NoFailure) { QTimer timer(this); connect(&timer, &QTimer::timeout, d, &QtcProcessPrivate::slotTimeout); timer.setInterval(1000); @@ -1523,7 +1529,7 @@ void QtcProcessPrivate::slotFinished(int exitCode, QProcess::ExitStatus status) emit q->finished(); } -void QtcProcessPrivate::slotError(QProcess::ProcessError error) +void QtcProcessPrivate::handleError(QProcess::ProcessError error, StartFailure startFailure) { m_hangTimerCount = 0; if (debug) @@ -1531,7 +1537,7 @@ void QtcProcessPrivate::slotError(QProcess::ProcessError error) // Was hang detected before and killed? if (m_result != QtcProcess::Hang) m_result = QtcProcess::StartFailed; - m_startFailure = true; + m_startFailure = startFailure; if (m_eventLoop) m_eventLoop->quit(); diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index 9ca0e228c3c..e30aeb70647 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -1219,17 +1219,14 @@ void SimpleTargetRunner::doStart(const Runnable &runnable, const IDevice::ConstP connect(&m_launcher, &ApplicationLauncher::processExited, this, [this, runnable](int exitCode, QProcess::ExitStatus status) { - QString msg; - if (status == QProcess::CrashExit) - msg = tr("%1 crashed."); - else - msg = tr("%2 exited with code %1").arg(exitCode); + if (m_stopReported) + return; + const QString msg = (status == QProcess::CrashExit) + ? tr("%1 crashed.") : tr("%2 exited with code %1").arg(exitCode); const QString displayName = runnable.command.executable().toUserOutput(); appendMessage(msg.arg(displayName), Utils::NormalMessageFormat); - if (!m_stopReported) { - m_stopReported = true; - reportStopped(); - } + m_stopReported = true; + reportStopped(); }); connect(&m_launcher, &ApplicationLauncher::error,