Commit 59535078 authored by hjk's avatar hjk

RemoteLinux: Base AbstractRemotetLinuxRunSupport on PE::TargetSupport

This essentially just puts the data members and most of the original
interface on the proper, i.e. the 'target', side of the tool/target
divide. Since the SimpleTargetRunner base already has an
ApplicationLauncher member, this can be used directly.

State handling and coordination between tool and target runner parts
stays as before for now, with unchanged 'custom' transition logic.
The plan here is to remove the custom state handling later, including
the two remaining cases of direct targetRunner->toolRunner calling
(startExecution, and adapterSetupFailed) for which this patch here
temporarily uses signal/slot connections.

Change-Id: I664f2e333b48b582befd0531a17d4008acac7c4c
Reviewed-by: Christian Kandeler's avatarChristian Kandeler <christian.kandeler@qt.io>
parent dce9aa21
......@@ -1189,6 +1189,11 @@ void TargetRunner::appendMessage(const QString &msg, OutputFormat format)
m_runControl->appendMessage(msg, format);
}
IDevice::ConstPtr TargetRunner::device() const
{
return m_runControl->device();
}
// ToolRunner
......
......@@ -457,6 +457,7 @@ public:
RunControl *runControl() const;
void appendMessage(const QString &msg, Utils::OutputFormat format);
IDevice::ConstPtr device() const;
virtual void prepare() { emit prepared(); }
virtual void start() { emit started(); }
......@@ -511,6 +512,8 @@ class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public TargetRunner
public:
explicit SimpleTargetRunner(RunControl *runControl);
ApplicationLauncher *applicationLauncher() { return &m_launcher; }
private:
void start() override;
void stop() override;
......
......@@ -42,7 +42,6 @@ class AbstractRemoteLinuxRunSupportPrivate
{
public:
AbstractRemoteLinuxRunSupport::State state = AbstractRemoteLinuxRunSupport::Inactive;
ApplicationLauncher appLauncher;
DeviceUsedPortsGatherer portsGatherer;
ApplicationLauncher fifoCreator;
Utils::PortList portList;
......@@ -54,7 +53,7 @@ public:
using namespace Internal;
AbstractRemoteLinuxRunSupport::AbstractRemoteLinuxRunSupport(RunControl *runControl)
: ToolRunner(runControl),
: SimpleTargetRunner(runControl),
d(new AbstractRemoteLinuxRunSupportPrivate)
{
}
......@@ -78,7 +77,9 @@ AbstractRemoteLinuxRunSupport::State AbstractRemoteLinuxRunSupport::state() cons
void AbstractRemoteLinuxRunSupport::handleResourcesError(const QString &message)
{
QTC_ASSERT(d->state == GatheringResources, return);
handleAdapterSetupFailed(message);
setFinished();
reset();
emit adapterSetupFailed(message);
}
void AbstractRemoteLinuxRunSupport::handleResourcesAvailable()
......@@ -86,18 +87,7 @@ void AbstractRemoteLinuxRunSupport::handleResourcesAvailable()
QTC_ASSERT(d->state == GatheringResources, return);
d->portList = device()->freePorts();
startExecution();
}
void AbstractRemoteLinuxRunSupport::handleAdapterSetupFailed(const QString &)
{
setFinished();
reset();
}
void AbstractRemoteLinuxRunSupport::handleAdapterSetupDone()
{
d->state = Running;
emit executionStartRequested();
}
void AbstractRemoteLinuxRunSupport::setFinished()
......@@ -105,7 +95,7 @@ void AbstractRemoteLinuxRunSupport::setFinished()
if (d->state == Inactive)
return;
if (d->state == Running)
d->appLauncher.stop();
applicationLauncher()->stop();
d->state = Inactive;
}
......@@ -170,13 +160,8 @@ void AbstractRemoteLinuxRunSupport::createRemoteFifo()
void AbstractRemoteLinuxRunSupport::reset()
{
d->portsGatherer.disconnect(this);
d->appLauncher.disconnect(this);
applicationLauncher()->disconnect(this);
d->state = Inactive;
}
ApplicationLauncher *AbstractRemoteLinuxRunSupport::appRunner() const
{
return &d->appLauncher;
}
} // namespace RemoteLinux
......@@ -32,16 +32,15 @@
#include <utils/port.h>
#include <QObject>
namespace RemoteLinux {
namespace Internal { class AbstractRemoteLinuxRunSupportPrivate; }
class REMOTELINUX_EXPORT AbstractRemoteLinuxRunSupport : public ProjectExplorer::ToolRunner
class REMOTELINUX_EXPORT AbstractRemoteLinuxRunSupport : public ProjectExplorer::SimpleTargetRunner
{
Q_OBJECT
protected:
public:
enum State
{
Inactive,
......@@ -49,19 +48,12 @@ protected:
StartingRunner,
Running
};
public:
explicit AbstractRemoteLinuxRunSupport(ProjectExplorer::RunControl *runControl);
~AbstractRemoteLinuxRunSupport();
protected:
void setState(State state);
State state() const;
ProjectExplorer::ApplicationLauncher *appRunner() const;
virtual void startExecution() = 0;
virtual void handleAdapterSetupFailed(const QString &error);
virtual void handleAdapterSetupDone();
void setFinished();
......@@ -73,19 +65,14 @@ protected:
void reset();
protected:
virtual void handleRemoteSetupRequested() = 0;
virtual void handleAppRunnerError(const QString &error) = 0;
virtual void handleRemoteOutput(const QByteArray &output) = 0;
virtual void handleRemoteErrorOutput(const QByteArray &output) = 0;
virtual void handleAppRunnerFinished(bool success) = 0;
virtual void handleProgressReport(const QString &progressOutput) = 0;
signals:
void adapterSetupFailed(const QString &error);
void executionStartRequested();
private:
void handleResourcesError(const QString &message);
void handleResourcesAvailable();
friend class Internal::AbstractRemoteLinuxRunSupportPrivate;
Internal::AbstractRemoteLinuxRunSupportPrivate * const d;
};
......
......@@ -78,7 +78,7 @@ public:
using namespace Internal;
RemoteLinuxAnalyzeSupport::RemoteLinuxAnalyzeSupport(RunControl *runControl)
: AbstractRemoteLinuxRunSupport(runControl),
: ToolRunner(runControl),
d(new RemoteLinuxAnalyzeSupportPrivate(runControl))
{
connect(runControl, &RunControl::starting,
......@@ -87,6 +87,13 @@ RemoteLinuxAnalyzeSupport::RemoteLinuxAnalyzeSupport(RunControl *runControl)
this, &RemoteLinuxAnalyzeSupport::remoteIsRunning);
connect(runControl, &RunControl::finished,
this, &RemoteLinuxAnalyzeSupport::handleProfilingFinished);
connect(qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl->targetRunner()),
&AbstractRemoteLinuxRunSupport::executionStartRequested,
this, &RemoteLinuxAnalyzeSupport::startExecution);
connect(qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl->targetRunner()),
&AbstractRemoteLinuxRunSupport::adapterSetupFailed,
this, &RemoteLinuxAnalyzeSupport::handleAdapterSetupFailed);
}
RemoteLinuxAnalyzeSupport::~RemoteLinuxAnalyzeSupport()
......@@ -96,49 +103,49 @@ RemoteLinuxAnalyzeSupport::~RemoteLinuxAnalyzeSupport()
void RemoteLinuxAnalyzeSupport::showMessage(const QString &msg, Utils::OutputFormat format)
{
if (state() != Inactive)
if (targetRunner()->state() != AbstractRemoteLinuxRunSupport::Inactive)
appendMessage(msg, format);
d->outputParser.processOutput(msg);
}
void RemoteLinuxAnalyzeSupport::handleRemoteSetupRequested()
{
QTC_ASSERT(state() == Inactive, return);
QTC_ASSERT(targetRunner()->state() == AbstractRemoteLinuxRunSupport::Inactive, return);
const Core::Id runMode = runControl()->runMode();
if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
showMessage(tr("Checking available ports...") + QLatin1Char('\n'),
Utils::NormalMessageFormat);
startPortsGathering();
targetRunner()->startPortsGathering();
} else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
showMessage(tr("Creating remote socket...") + QLatin1Char('\n'),
Utils::NormalMessageFormat);
createRemoteFifo();
targetRunner()->createRemoteFifo();
}
}
void RemoteLinuxAnalyzeSupport::startExecution()
{
QTC_ASSERT(state() == GatheringResources, return);
QTC_ASSERT(targetRunner()->state() == AbstractRemoteLinuxRunSupport::GatheringResources, return);
const Core::Id runMode = runControl()->runMode();
if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
d->qmlPort = findPort();
d->qmlPort = targetRunner()->findPort();
if (!d->qmlPort.isValid()) {
handleAdapterSetupFailed(tr("Not enough free ports on device for profiling."));
return;
}
} else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
d->remoteFifo = fifo();
d->remoteFifo = targetRunner()->fifo();
if (d->remoteFifo.isEmpty()) {
handleAdapterSetupFailed(tr("FIFO for profiling data could not be created."));
return;
}
}
setState(StartingRunner);
targetRunner()->setState(AbstractRemoteLinuxRunSupport::StartingRunner);
ApplicationLauncher *runner = appRunner();
ApplicationLauncher *runner = targetRunner()->applicationLauncher();
connect(runner, &ApplicationLauncher::remoteStderr,
this, &RemoteLinuxAnalyzeSupport::handleRemoteErrorOutput);
connect(runner, &ApplicationLauncher::remoteStdout,
......@@ -183,16 +190,16 @@ void RemoteLinuxAnalyzeSupport::startExecution()
void RemoteLinuxAnalyzeSupport::handleAppRunnerError(const QString &error)
{
if (state() == Running)
if (targetRunner()->state() == AbstractRemoteLinuxRunSupport::Running)
showMessage(error, Utils::ErrorMessageFormat);
else if (state() != Inactive)
else if (targetRunner()->state() != AbstractRemoteLinuxRunSupport::Inactive)
handleAdapterSetupFailed(error);
}
void RemoteLinuxAnalyzeSupport::handleAppRunnerFinished(bool success)
{
// reset needs to be called first to ensure that the correct state is set.
reset();
targetRunner()->reset();
if (!success)
showMessage(tr("Failure running remote process."), Utils::NormalMessageFormat);
runControl()->notifyRemoteFinished();
......@@ -200,7 +207,7 @@ void RemoteLinuxAnalyzeSupport::handleAppRunnerFinished(bool success)
void RemoteLinuxAnalyzeSupport::handleProfilingFinished()
{
setFinished();
targetRunner()->setFinished();
}
void RemoteLinuxAnalyzeSupport::remoteIsRunning()
......@@ -208,16 +215,22 @@ void RemoteLinuxAnalyzeSupport::remoteIsRunning()
runControl()->notifyRemoteSetupDone(d->qmlPort);
}
AbstractRemoteLinuxRunSupport *RemoteLinuxAnalyzeSupport::targetRunner() const
{
return qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl()->targetRunner());
}
void RemoteLinuxAnalyzeSupport::handleRemoteOutput(const QByteArray &output)
{
QTC_ASSERT(state() == Inactive || state() == Running, return);
QTC_ASSERT(targetRunner()->state() == AbstractRemoteLinuxRunSupport::Inactive
|| targetRunner()->state() == AbstractRemoteLinuxRunSupport::Running, return);
showMessage(QString::fromUtf8(output), Utils::StdOutFormat);
}
void RemoteLinuxAnalyzeSupport::handleRemoteErrorOutput(const QByteArray &output)
{
QTC_ASSERT(state() != GatheringResources, return);
QTC_ASSERT(targetRunner()->state() != AbstractRemoteLinuxRunSupport::GatheringResources, return);
showMessage(QString::fromUtf8(output), Utils::StdErrFormat);
}
......@@ -229,15 +242,14 @@ void RemoteLinuxAnalyzeSupport::handleProgressReport(const QString &progressOutp
void RemoteLinuxAnalyzeSupport::handleAdapterSetupFailed(const QString &error)
{
AbstractRemoteLinuxRunSupport::handleAdapterSetupFailed(error);
showMessage(tr("Initial setup failed: %1").arg(error), Utils::NormalMessageFormat);
}
void RemoteLinuxAnalyzeSupport::handleRemoteProcessStarted()
{
QTC_ASSERT(state() == StartingRunner, return);
QTC_ASSERT(targetRunner()->state() == AbstractRemoteLinuxRunSupport::StartingRunner, return);
handleAdapterSetupDone();
targetRunner()->setState(AbstractRemoteLinuxRunSupport::Running);
}
} // namespace RemoteLinux
......@@ -36,29 +36,29 @@ namespace RemoteLinux {
namespace Internal { class RemoteLinuxAnalyzeSupportPrivate; }
class REMOTELINUX_EXPORT RemoteLinuxAnalyzeSupport : public AbstractRemoteLinuxRunSupport
class REMOTELINUX_EXPORT RemoteLinuxAnalyzeSupport : public ProjectExplorer::ToolRunner
{
Q_OBJECT
public:
RemoteLinuxAnalyzeSupport(ProjectExplorer::RunControl *runControl);
~RemoteLinuxAnalyzeSupport() override;
protected:
void startExecution() override;
void handleAdapterSetupFailed(const QString &error) override;
private:
void handleRemoteSetupRequested() override;
void handleAppRunnerError(const QString &error) override;
void handleRemoteOutput(const QByteArray &output) override;
void handleRemoteErrorOutput(const QByteArray &output) override;
void handleAppRunnerFinished(bool success) override;
void handleProgressReport(const QString &progressOutput) override;
void startExecution();
void handleAdapterSetupFailed(const QString &error);
void handleRemoteSetupRequested();
void handleAppRunnerError(const QString &error);
void handleRemoteOutput(const QByteArray &output);
void handleRemoteErrorOutput(const QByteArray &output);
void handleAppRunnerFinished(bool success);
void handleProgressReport(const QString &progressOutput);
void handleRemoteProcessStarted();
void handleProfilingFinished();
void remoteIsRunning();
AbstractRemoteLinuxRunSupport *targetRunner() const;
void showMessage(const QString &, Utils::OutputFormat);
......
......@@ -73,14 +73,23 @@ public:
using namespace Internal;
LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl)
: AbstractRemoteLinuxRunSupport(runControl),
LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl,
const Debugger::DebuggerStartParameters &sp,
QString *errorMessage)
: DebuggerRunTool(runControl, sp, errorMessage),
d(new LinuxDeviceDebugSupportPrivate(runControl->runConfiguration()))
{
connect(this->runControl(), &DebuggerRunControl::requestRemoteSetup,
this, &LinuxDeviceDebugSupport::handleRemoteSetupRequested);
connect(runControl, &RunControl::finished,
this, &LinuxDeviceDebugSupport::handleDebuggingFinished);
connect(qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl->targetRunner()),
&AbstractRemoteLinuxRunSupport::executionStartRequested,
this, &LinuxDeviceDebugSupport::startExecution);
connect(qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl->targetRunner()),
&AbstractRemoteLinuxRunSupport::adapterSetupFailed,
this, &LinuxDeviceDebugSupport::handleAdapterSetupFailed);
}
LinuxDeviceDebugSupport::~LinuxDeviceDebugSupport()
......@@ -100,46 +109,57 @@ bool LinuxDeviceDebugSupport::isQmlDebugging() const
void LinuxDeviceDebugSupport::showMessage(const QString &msg, int channel)
{
if (state() != Inactive)
if (state() != AbstractRemoteLinuxRunSupport::Inactive)
runControl()->toolRunner()->showMessage(msg, channel);
}
DebuggerRunControl *LinuxDeviceDebugSupport::runControl() const
{
return qobject_cast<DebuggerRunControl *>(AbstractRemoteLinuxRunSupport::runControl());
return qobject_cast<DebuggerRunControl *>(ToolRunner::runControl());
}
AbstractRemoteLinuxRunSupport *LinuxDeviceDebugSupport::targetRunner() const
{
return qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl()->targetRunner());
}
AbstractRemoteLinuxRunSupport::State LinuxDeviceDebugSupport::state() const
{
AbstractRemoteLinuxRunSupport *runner = targetRunner();
return runner ? runner->state() : AbstractRemoteLinuxRunSupport::Inactive;
}
void LinuxDeviceDebugSupport::handleRemoteSetupRequested()
{
QTC_ASSERT(state() == Inactive, return);
QTC_ASSERT(state() == AbstractRemoteLinuxRunSupport::Inactive, return);
showMessage(tr("Checking available ports...") + QLatin1Char('\n'), LogStatus);
startPortsGathering();
targetRunner()->startPortsGathering();
}
void LinuxDeviceDebugSupport::startExecution()
{
QTC_ASSERT(state() == GatheringResources, return);
QTC_ASSERT(state() == AbstractRemoteLinuxRunSupport::GatheringResources, return);
if (d->cppDebugging) {
d->gdbServerPort = findPort();
d->gdbServerPort = targetRunner()->findPort();
if (!d->gdbServerPort.isValid()) {
handleAdapterSetupFailed(tr("Not enough free ports on device for C++ debugging."));
return;
}
}
if (d->qmlDebugging) {
d->qmlPort = findPort();
d->qmlPort = targetRunner()->findPort();
if (!d->qmlPort.isValid()) {
handleAdapterSetupFailed(tr("Not enough free ports on device for QML debugging."));
return;
}
}
setState(StartingRunner);
targetRunner()->setState(AbstractRemoteLinuxRunSupport::StartingRunner);
d->gdbserverOutput.clear();
ApplicationLauncher *launcher = appRunner();
ApplicationLauncher *launcher = targetRunner()->applicationLauncher();
connect(launcher, &ApplicationLauncher::remoteStderr,
this, &LinuxDeviceDebugSupport::handleRemoteErrorOutput);
connect(launcher, &ApplicationLauncher::remoteStdout,
......@@ -183,54 +203,55 @@ Runnable LinuxDeviceDebugSupport::realRunnable() const
void LinuxDeviceDebugSupport::handleAppRunnerError(const QString &error)
{
if (state() == Running) {
if (state() == AbstractRemoteLinuxRunSupport::Running) {
showMessage(error, AppError);
runControl()->toolRunner()->notifyInferiorIll();
} else if (state() != Inactive) {
} else if (state() != AbstractRemoteLinuxRunSupport::Inactive) {
handleAdapterSetupFailed(error);
}
}
void LinuxDeviceDebugSupport::handleAppRunnerFinished(bool success)
{
if (state() == Inactive)
if (state() == AbstractRemoteLinuxRunSupport::Inactive)
return;
if (state() == Running) {
if (state() == AbstractRemoteLinuxRunSupport::Running) {
// The QML engine does not realize on its own that the application has finished.
if (d->qmlDebugging && !d->cppDebugging)
runControl()->toolRunner()->quitDebugger();
else if (!success)
runControl()->toolRunner()->notifyInferiorIll();
} else if (state() == StartingRunner) {
} else if (state() == AbstractRemoteLinuxRunSupport::StartingRunner) {
RemoteSetupResult result;
result.success = false;
result.reason = tr("Debugging failed.");
runControl()->toolRunner()->notifyEngineRemoteSetupFinished(result);
}
reset();
targetRunner()->reset();
}
void LinuxDeviceDebugSupport::handleDebuggingFinished()
{
setFinished();
reset();
targetRunner()->setFinished();
targetRunner()->reset();
}
void LinuxDeviceDebugSupport::handleRemoteOutput(const QByteArray &output)
{
QTC_ASSERT(state() == Inactive || state() == Running, return);
QTC_ASSERT(state() == AbstractRemoteLinuxRunSupport::Inactive
|| state() == AbstractRemoteLinuxRunSupport::Running, return);
showMessage(QString::fromUtf8(output), AppOutput);
}
void LinuxDeviceDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
{
QTC_ASSERT(state() != GatheringResources, return);
QTC_ASSERT(state() != AbstractRemoteLinuxRunSupport::GatheringResources, return);
showMessage(QString::fromUtf8(output), AppError);
if (state() == StartingRunner && d->cppDebugging) {
if (state() == AbstractRemoteLinuxRunSupport::StartingRunner && d->cppDebugging) {
d->gdbserverOutput += output;
if (d->gdbserverOutput.contains("Listening on port")) {
handleAdapterSetupDone();
......@@ -246,8 +267,6 @@ void LinuxDeviceDebugSupport::handleProgressReport(const QString &progressOutput
void LinuxDeviceDebugSupport::handleAdapterSetupFailed(const QString &error)
{
AbstractRemoteLinuxRunSupport::handleAdapterSetupFailed(error);
RemoteSetupResult result;
result.success = false;
result.reason = tr("Initial setup failed: %1").arg(error);
......@@ -256,7 +275,7 @@ void LinuxDeviceDebugSupport::handleAdapterSetupFailed(const QString &error)
void LinuxDeviceDebugSupport::handleAdapterSetupDone()
{
AbstractRemoteLinuxRunSupport::handleAdapterSetupDone();
targetRunner()->setState(AbstractRemoteLinuxRunSupport::Running);
RemoteSetupResult result;
result.success = true;
......@@ -268,7 +287,7 @@ void LinuxDeviceDebugSupport::handleAdapterSetupDone()
void LinuxDeviceDebugSupport::handleRemoteProcessStarted()
{
QTC_ASSERT(d->qmlDebugging && !d->cppDebugging, return);
QTC_ASSERT(state() == StartingRunner, return);
QTC_ASSERT(state() == AbstractRemoteLinuxRunSupport::StartingRunner, return);
handleAdapterSetupDone();
}
......
......@@ -27,42 +27,47 @@
#include "abstractremotelinuxrunsupport.h"
namespace Debugger { class DebuggerRunControl; }
#include <debugger/debuggerruncontrol.h>
namespace RemoteLinux {
namespace Internal { class LinuxDeviceDebugSupportPrivate; }
class REMOTELINUX_EXPORT LinuxDeviceDebugSupport : public AbstractRemoteLinuxRunSupport
class REMOTELINUX_EXPORT LinuxDeviceDebugSupport : public Debugger::DebuggerRunTool
{
Q_OBJECT
public:
LinuxDeviceDebugSupport(ProjectExplorer::RunControl *runControl);
LinuxDeviceDebugSupport(ProjectExplorer::RunControl *runControl,
const Debugger::DebuggerStartParameters &sp,
QString *errorMessage = nullptr);
~LinuxDeviceDebugSupport() override;
protected:
virtual ProjectExplorer::Runnable realRunnable() const;
bool isCppDebugging() const;
bool isQmlDebugging() const;
void startExecution() override;
void handleAdapterSetupFailed(const QString &error) override;
void handleAdapterSetupDone() override;
Debugger::DebuggerRunControl *runControl() const;
private:
void handleRemoteSetupRequested() override;
void handleAppRunnerError(const QString &error) override;
void handleRemoteOutput(const QByteArray &output) override;
void handleRemoteErrorOutput(const QByteArray &output) override;
void handleAppRunnerFinished(bool success) override;
void handleProgressReport(const QString &progressOutput) override;
void startExecution();
void handleAdapterSetupFailed(const QString &error);
void handleRemoteSetupRequested();
void handleAppRunnerError(const QString &error);
void handleRemoteOutput(const QByteArray &output);
void handleRemoteErrorOutput(const QByteArray &output);
void handleAppRunnerFinished(bool success);
void handleProgressReport(const QString &progressOutput);
void handleRemoteProcessStarted();