ProjectExplorer: Consolidate ApplicationLauncher

Both local and remote runs now use QtcProcess or a derived class.

Change-Id: Idd0645a5645ab91a6d49b9839d021c6757296d00
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
hjk
2022-02-15 13:56:35 +01:00
parent 47957de2dc
commit c655bac6fa

View File

@@ -82,7 +82,7 @@ public:
void checkLocalDebugOutput(qint64 pid, const QString &message); void checkLocalDebugOutput(qint64 pid, const QString &message);
void localProcessDone(int, QProcess::ExitStatus); void localProcessDone(int, QProcess::ExitStatus);
qint64 applicationPID() const; qint64 applicationPID() const;
bool isLocalRunning() const; bool isRunning() const;
// Remote // Remote
void doReportError(const QString &message, void doReportError(const QString &message,
@@ -99,8 +99,9 @@ public:
bool m_isLocal = true; bool m_isLocal = true;
bool m_runAsRoot = false; bool m_runAsRoot = false;
std::unique_ptr<QtcProcess> m_process;
// Local // Local
std::unique_ptr<QtcProcess> m_localProcess;
bool m_useTerminal = false; bool m_useTerminal = false;
QProcess::ProcessChannelMode m_processChannelMode; QProcess::ProcessChannelMode m_processChannelMode;
// Keep track whether we need to emit a finished signal // Keep track whether we need to emit a finished signal
@@ -113,7 +114,6 @@ public:
qint64 m_listeningPid = 0; qint64 m_listeningPid = 0;
// Remote // Remote
DeviceProcess *m_deviceProcess = nullptr;
QString m_remoteErrorString; QString m_remoteErrorString;
QProcess::ProcessError m_remoteError = QProcess::UnknownError; QProcess::ProcessError m_remoteError = QProcess::UnknownError;
QProcess::ExitStatus m_remoteExitStatus = QProcess::CrashExit; QProcess::ExitStatus m_remoteExitStatus = QProcess::CrashExit;
@@ -179,10 +179,10 @@ void ApplicationLauncher::stop()
void ApplicationLauncherPrivate::stop() void ApplicationLauncherPrivate::stop()
{ {
if (m_isLocal) { if (m_isLocal) {
if (!isLocalRunning()) if (!isRunning())
return; return;
QTC_ASSERT(m_localProcess, return); QTC_ASSERT(m_process, return);
m_localProcess->stopProcess(); m_process->stopProcess();
localProcessDone(0, QProcess::CrashExit); localProcessDone(0, QProcess::CrashExit);
} else { } else {
if (m_stopRequested) if (m_stopRequested)
@@ -193,7 +193,7 @@ void ApplicationLauncherPrivate::stop()
Utils::NormalMessageFormat); Utils::NormalMessageFormat);
switch (m_state) { switch (m_state) {
case Run: case Run:
m_deviceProcess->terminate(); m_process->terminate();
break; break;
case Inactive: case Inactive:
break; break;
@@ -203,7 +203,7 @@ void ApplicationLauncherPrivate::stop()
bool ApplicationLauncher::isRunning() const bool ApplicationLauncher::isRunning() const
{ {
return d->isLocalRunning(); return d->isRunning();
} }
bool ApplicationLauncher::isLocal() const bool ApplicationLauncher::isLocal() const
@@ -211,11 +211,11 @@ bool ApplicationLauncher::isLocal() const
return d->m_isLocal; return d->m_isLocal;
} }
bool ApplicationLauncherPrivate::isLocalRunning() const bool ApplicationLauncherPrivate::isRunning() const
{ {
if (!m_localProcess) if (!m_process)
return false; return false;
return m_localProcess->state() != QProcess::NotRunning; return m_process->state() != QProcess::NotRunning;
} }
ProcessHandle ApplicationLauncher::applicationPID() const ProcessHandle ApplicationLauncher::applicationPID() const
@@ -225,23 +225,23 @@ ProcessHandle ApplicationLauncher::applicationPID() const
qint64 ApplicationLauncherPrivate::applicationPID() const qint64 ApplicationLauncherPrivate::applicationPID() const
{ {
if (!isLocalRunning()) if (!isRunning())
return 0; return 0;
return m_localProcess->processId(); return m_process->processId();
} }
QString ApplicationLauncher::errorString() const QString ApplicationLauncher::errorString() const
{ {
if (d->m_isLocal) if (d->m_isLocal)
return d->m_localProcess ? d->m_localProcess->errorString() : QString(); return d->m_process ? d->m_process->errorString() : QString();
return d->m_remoteErrorString; return d->m_remoteErrorString;
} }
QProcess::ProcessError ApplicationLauncher::processError() const QProcess::ProcessError ApplicationLauncher::processError() const
{ {
if (d->m_isLocal) if (d->m_isLocal)
return d->m_localProcess ? d->m_localProcess->error() : QProcess::UnknownError; return d->m_process ? d->m_process->error() : QProcess::UnknownError;
return d->m_remoteError; return d->m_remoteError;
} }
@@ -249,15 +249,15 @@ void ApplicationLauncherPrivate::localProcessError(QProcess::ProcessError error)
{ {
// TODO: why below handlings are different? // TODO: why below handlings are different?
if (m_useTerminal) { if (m_useTerminal) {
emit q->appendMessage(m_localProcess->errorString(), ErrorMessageFormat); emit q->appendMessage(m_process->errorString(), ErrorMessageFormat);
if (m_processRunning && m_localProcess->processId() == 0) { if (m_processRunning && m_process->processId() == 0) {
m_processRunning = false; m_processRunning = false;
emit q->processExited(-1, QProcess::NormalExit); emit q->processExited(-1, QProcess::NormalExit);
} }
} else { } else {
QString error; QString error;
QProcess::ExitStatus status = QProcess::NormalExit; QProcess::ExitStatus status = QProcess::NormalExit;
switch (m_localProcess->error()) { switch (m_process->error()) {
case QProcess::FailedToStart: case QProcess::FailedToStart:
error = ApplicationLauncher::tr("Failed to start program. Path or permissions wrong?"); error = ApplicationLauncher::tr("Failed to start program. Path or permissions wrong?");
break; break;
@@ -269,7 +269,7 @@ void ApplicationLauncherPrivate::localProcessError(QProcess::ProcessError error)
} }
if (!error.isEmpty()) if (!error.isEmpty())
emit q->appendMessage(error, ErrorMessageFormat); emit q->appendMessage(error, ErrorMessageFormat);
if (m_processRunning && !isLocalRunning()) { if (m_processRunning && !isRunning()) {
m_processRunning = false; m_processRunning = false;
emit q->processExited(-1, status); emit q->processExited(-1, status);
} }
@@ -279,7 +279,7 @@ void ApplicationLauncherPrivate::localProcessError(QProcess::ProcessError error)
void ApplicationLauncherPrivate::readLocalStandardOutput() void ApplicationLauncherPrivate::readLocalStandardOutput()
{ {
const QByteArray data = m_localProcess->readAllStandardOutput(); const QByteArray data = m_process->readAllStandardOutput();
const QString msg = m_outputCodec->toUnicode( const QString msg = m_outputCodec->toUnicode(
data.constData(), data.length(), &m_outputCodecState); data.constData(), data.length(), &m_outputCodecState);
emit q->appendMessage(msg, StdOutFormat, false); emit q->appendMessage(msg, StdOutFormat, false);
@@ -287,7 +287,7 @@ void ApplicationLauncherPrivate::readLocalStandardOutput()
void ApplicationLauncherPrivate::readLocalStandardError() void ApplicationLauncherPrivate::readLocalStandardError()
{ {
const QByteArray data = m_localProcess->readAllStandardError(); const QByteArray data = m_process->readAllStandardError();
const QString msg = m_outputCodec->toUnicode( const QString msg = m_outputCodec->toUnicode(
data.constData(), data.length(), &m_errorCodecState); data.constData(), data.length(), &m_errorCodecState);
emit q->appendMessage(msg, StdErrFormat, false); emit q->appendMessage(msg, StdErrFormat, false);
@@ -341,38 +341,36 @@ void ApplicationLauncherPrivate::start(const IDevice::ConstPtr &device, bool loc
m_isLocal = local; m_isLocal = local;
if (m_isLocal) { if (m_isLocal) {
m_localProcess.reset(new QtcProcess(this)); m_process.reset(new QtcProcess(this));
m_localProcess->setTerminalMode( m_process->setProcessChannelMode(m_processChannelMode);
m_useTerminal ? QtcProcess::TerminalOn : QtcProcess::TerminalOff);
m_localProcess->setProcessChannelMode(m_processChannelMode);
if (m_processChannelMode == QProcess::SeparateChannels) { if (m_processChannelMode == QProcess::SeparateChannels) {
connect(m_localProcess.get(), &QtcProcess::readyReadStandardError, connect(m_process.get(), &QtcProcess::readyReadStandardError,
this, &ApplicationLauncherPrivate::readLocalStandardError); this, &ApplicationLauncherPrivate::readLocalStandardError);
} }
if (!m_useTerminal) { if (!m_useTerminal) {
connect(m_localProcess.get(), &QtcProcess::readyReadStandardOutput, connect(m_process.get(), &QtcProcess::readyReadStandardOutput,
this, &ApplicationLauncherPrivate::readLocalStandardOutput); this, &ApplicationLauncherPrivate::readLocalStandardOutput);
} }
connect(m_localProcess.get(), &QtcProcess::started, connect(m_process.get(), &QtcProcess::started,
this, &ApplicationLauncherPrivate::handleProcessStarted); this, &ApplicationLauncherPrivate::handleProcessStarted);
connect(m_localProcess.get(), &QtcProcess::finished, this, [this] { connect(m_process.get(), &QtcProcess::finished, this, [this] {
localProcessDone(m_localProcess->exitCode(), m_localProcess->exitStatus()); localProcessDone(m_process->exitCode(), m_process->exitStatus());
}); });
connect(m_localProcess.get(), &QtcProcess::errorOccurred, connect(m_process.get(), &QtcProcess::errorOccurred,
this, &ApplicationLauncherPrivate::localProcessError); this, &ApplicationLauncherPrivate::localProcessError);
// Work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch' ...) // Work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch' ...)
const FilePath fixedPath = m_runnable.workingDirectory.normalizedPathName(); const FilePath fixedPath = m_runnable.workingDirectory.normalizedPathName();
m_localProcess->setWorkingDirectory(fixedPath); m_process->setWorkingDirectory(fixedPath);
Environment env = m_runnable.environment; Environment env = m_runnable.environment;
if (m_runAsRoot) if (m_runAsRoot)
RunControl::provideAskPassEntry(env); RunControl::provideAskPassEntry(env);
m_localProcess->setEnvironment(env); m_process->setEnvironment(env);
m_processRunning = true; m_processRunning = true;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -388,9 +386,8 @@ void ApplicationLauncherPrivate::start(const IDevice::ConstPtr &device, bool loc
cmdLine = disclaim; cmdLine = disclaim;
} }
m_localProcess->setRunAsRoot(m_runAsRoot); m_process->setRunAsRoot(m_runAsRoot);
m_localProcess->setCommand(cmdLine); m_process->setCommand(cmdLine);
m_localProcess->start();
} else { } else {
QTC_ASSERT(m_state == Inactive, return); QTC_ASSERT(m_state == Inactive, return);
@@ -416,32 +413,32 @@ void ApplicationLauncherPrivate::start(const IDevice::ConstPtr &device, bool loc
m_stopRequested = false; m_stopRequested = false;
m_remoteExitStatus = QProcess::NormalExit; m_remoteExitStatus = QProcess::NormalExit;
m_deviceProcess = device->createProcess(this); m_process.reset(device->createProcess(this));
m_deviceProcess->setTerminalMode(m_useTerminal ? QtcProcess::TerminalOn connect(m_process.get(), &QtcProcess::started,
: QtcProcess::TerminalOff);
connect(m_deviceProcess, &DeviceProcess::started,
q, &ApplicationLauncher::processStarted); q, &ApplicationLauncher::processStarted);
connect(m_deviceProcess, &DeviceProcess::readyReadStandardOutput, connect(m_process.get(), &QtcProcess::readyReadStandardOutput,
this, &ApplicationLauncherPrivate::handleRemoteStdout); this, &ApplicationLauncherPrivate::handleRemoteStdout);
connect(m_deviceProcess, &DeviceProcess::readyReadStandardError, connect(m_process.get(), &QtcProcess::readyReadStandardError,
this, &ApplicationLauncherPrivate::handleRemoteStderr); this, &ApplicationLauncherPrivate::handleRemoteStderr);
connect(m_deviceProcess, &DeviceProcess::errorOccurred, connect(m_process.get(), &QtcProcess::errorOccurred,
this, &ApplicationLauncherPrivate::handleApplicationError); this, &ApplicationLauncherPrivate::handleApplicationError);
connect(m_deviceProcess, &DeviceProcess::finished, connect(m_process.get(), &QtcProcess::finished,
this, &ApplicationLauncherPrivate::handleApplicationFinished); this, &ApplicationLauncherPrivate::handleApplicationFinished);
m_deviceProcess->setCommand(m_runnable.command); m_process->setCommand(m_runnable.command);
m_deviceProcess->setWorkingDirectory(m_runnable.workingDirectory); m_process->setWorkingDirectory(m_runnable.workingDirectory);
m_deviceProcess->setEnvironment(m_runnable.environment); m_process->setEnvironment(m_runnable.environment);
m_deviceProcess->setExtraData(m_runnable.extraData); m_process->setExtraData(m_runnable.extraData);
m_deviceProcess->start();
} }
m_process->setTerminalMode(m_useTerminal ? QtcProcess::TerminalOn : QtcProcess::TerminalOff);
m_process->start();
} }
void ApplicationLauncherPrivate::handleApplicationError(QProcess::ProcessError error) void ApplicationLauncherPrivate::handleApplicationError(QProcess::ProcessError error)
{ {
if (error == QProcess::FailedToStart) { if (error == QProcess::FailedToStart) {
doReportError(ApplicationLauncher::tr("Application failed to start: %1") doReportError(ApplicationLauncher::tr("Application failed to start: %1")
.arg(m_deviceProcess->errorString())); .arg(m_process->errorString()));
setFinished(); setFinished();
} }
} }
@@ -452,8 +449,8 @@ void ApplicationLauncherPrivate::setFinished()
return; return;
int exitCode = 0; int exitCode = 0;
if (m_deviceProcess) if (m_process)
exitCode = m_deviceProcess->exitCode(); exitCode = m_process->exitCode();
m_state = Inactive; m_state = Inactive;
emit q->processExited(exitCode, m_remoteExitStatus); emit q->processExited(exitCode, m_remoteExitStatus);
@@ -463,22 +460,22 @@ void ApplicationLauncherPrivate::handleApplicationFinished()
{ {
QTC_ASSERT(m_state == Run, return); QTC_ASSERT(m_state == Run, return);
if (m_deviceProcess->exitStatus() == QProcess::CrashExit) if (m_process->exitStatus() == QProcess::CrashExit)
doReportError(m_deviceProcess->errorString(), QProcess::Crashed); doReportError(m_process->errorString(), QProcess::Crashed);
setFinished(); setFinished();
} }
void ApplicationLauncherPrivate::handleRemoteStdout() void ApplicationLauncherPrivate::handleRemoteStdout()
{ {
QTC_ASSERT(m_state == Run, return); QTC_ASSERT(m_state == Run, return);
const QByteArray output = m_deviceProcess->readAllStandardOutput(); const QByteArray output = m_process->readAllStandardOutput();
emit q->appendMessage(QString::fromUtf8(output), Utils::StdOutFormat, false); emit q->appendMessage(QString::fromUtf8(output), Utils::StdOutFormat, false);
} }
void ApplicationLauncherPrivate::handleRemoteStderr() void ApplicationLauncherPrivate::handleRemoteStderr()
{ {
QTC_ASSERT(m_state == Run, return); QTC_ASSERT(m_state == Run, return);
const QByteArray output = m_deviceProcess->readAllStandardError(); const QByteArray output = m_process->readAllStandardError();
emit q->appendMessage(QString::fromUtf8(output), Utils::StdErrFormat, false); emit q->appendMessage(QString::fromUtf8(output), Utils::StdErrFormat, false);
} }