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 <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2021-10-26 11:10:06 +02:00
parent de2423f514
commit 0556eec9b7
2 changed files with 22 additions and 19 deletions

View File

@@ -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();

View File

@@ -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();
}
});
connect(&m_launcher, &ApplicationLauncher::error,