ProjectExplorer/Debugger/RL: Make run control state transitions more uniform

Forward all tool and target activities to run control, and initiate
further state transitions (only) from there. Also, make sure
tool/target's on finished() triggered on all finishing code paths.

After that, the base state handling is sufficient to handle remote linux
running and debugging.

Change-Id: I0150ef249c9ad0b7b8ac7192be6dc860c9ca8fc5
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2017-05-04 12:12:27 +02:00
parent ac59e2be40
commit 2a46b1521d
14 changed files with 385 additions and 500 deletions
+28 -24
View File
@@ -674,6 +674,7 @@ void DebuggerEngine::handleStartFailed()
// Called from RunControl. // Called from RunControl.
void DebuggerEngine::handleFinished() void DebuggerEngine::handleFinished()
{ {
setState(DebuggerFinished);
showMessage("HANDLE RUNCONTROL FINISHED"); showMessage("HANDLE RUNCONTROL FINISHED");
d->m_runTool.clear(); d->m_runTool.clear();
d->m_progress.setProgressValue(1000); d->m_progress.setProgressValue(1000);
@@ -821,7 +822,7 @@ void DebuggerEngine::notifyEngineSetupOk()
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
setState(EngineSetupOk); setState(EngineSetupOk);
runTool()->reportPrepared(); runTool()->reportSuccess();
} }
void DebuggerEngine::setupSlaveInferior() void DebuggerEngine::setupSlaveInferior()
@@ -907,7 +908,7 @@ void DebuggerEngine::notifyEngineRequestRemoteSetup()
<< "remoteSetupState" << d->remoteSetupState()); << "remoteSetupState" << d->remoteSetupState());
d->setRemoteSetupState(RemoteSetupRequested); d->setRemoteSetupState(RemoteSetupRequested);
runTool()->requestRemoteSetup(); runTool()->doRemoteSetup();
} }
void DebuggerEngine::notifyEngineRemoteServerRunning(const QString &, int /*pid*/) void DebuggerEngine::notifyEngineRemoteServerRunning(const QString &, int /*pid*/)
@@ -915,6 +916,30 @@ void DebuggerEngine::notifyEngineRemoteServerRunning(const QString &, int /*pid*
showMessage("NOTE: REMOTE SERVER RUNNING IN MULTIMODE"); showMessage("NOTE: REMOTE SERVER RUNNING IN MULTIMODE");
} }
void DebuggerEngine::setRemoteParameters(const RemoteSetupResult &result)
{
showMessage(QString("NOTE: REMOTE SETUP DONE: GDB SERVER PORT: %1 QML PORT %2")
.arg(result.gdbServerPort.number()).arg(result.qmlServerPort.number()));
if (result.gdbServerPort.isValid()) {
QString &rc = d->m_runParameters.remoteChannel;
const int sepIndex = rc.lastIndexOf(':');
if (sepIndex != -1) {
rc.replace(sepIndex + 1, rc.count() - sepIndex - 1,
QString::number(result.gdbServerPort.number()));
}
} else if (result.inferiorPid != InvalidPid && runParameters().startMode == AttachExternal) {
// e.g. iOS Simulator
runParameters().attachPID = ProcessHandle(result.inferiorPid);
}
if (result.qmlServerPort.isValid()) {
d->m_runParameters.qmlServer.port = result.qmlServerPort;
d->m_runParameters.inferior.commandLineArguments.replace("%qml_port%",
QString::number(result.qmlServerPort.number()));
}
}
void DebuggerEngine::notifyEngineRemoteSetupFinished(const RemoteSetupResult &result) void DebuggerEngine::notifyEngineRemoteSetupFinished(const RemoteSetupResult &result)
{ {
QTC_ASSERT(state() == EngineSetupRequested QTC_ASSERT(state() == EngineSetupRequested
@@ -926,30 +951,9 @@ void DebuggerEngine::notifyEngineRemoteSetupFinished(const RemoteSetupResult &re
qDebug() << this << "remoteSetupState" << d->remoteSetupState()); qDebug() << this << "remoteSetupState" << d->remoteSetupState());
if (result.success) { if (result.success) {
showMessage(QString("NOTE: REMOTE SETUP DONE: GDB SERVER PORT: %1 QML PORT %2")
.arg(result.gdbServerPort.number()).arg(result.qmlServerPort.number()));
if (d->remoteSetupState() != RemoteSetupCancelled) if (d->remoteSetupState() != RemoteSetupCancelled)
d->setRemoteSetupState(RemoteSetupSucceeded); d->setRemoteSetupState(RemoteSetupSucceeded);
setRemoteParameters(result);
if (result.gdbServerPort.isValid()) {
QString &rc = d->m_runParameters.remoteChannel;
const int sepIndex = rc.lastIndexOf(':');
if (sepIndex != -1) {
rc.replace(sepIndex + 1, rc.count() - sepIndex - 1,
QString::number(result.gdbServerPort.number()));
}
} else if (result.inferiorPid != InvalidPid && runParameters().startMode == AttachExternal) {
// e.g. iOS Simulator
runParameters().attachPID = ProcessHandle(result.inferiorPid);
}
if (result.qmlServerPort.isValid()) {
d->m_runParameters.qmlServer.port = result.qmlServerPort;
d->m_runParameters.inferior.commandLineArguments.replace("%qml_port%",
QString::number(result.qmlServerPort.number()));
}
} else { } else {
d->setRemoteSetupState(RemoteSetupFailed); d->setRemoteSetupState(RemoteSetupFailed);
showMessage("NOTE: REMOTE SETUP FAILED: " + result.reason); showMessage("NOTE: REMOTE SETUP FAILED: " + result.reason);
+2
View File
@@ -381,6 +381,8 @@ protected:
void notifyDebuggerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus, void notifyDebuggerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus,
const QString &backendName); const QString &backendName);
void setRemoteParameters(const RemoteSetupResult &result);
protected: protected:
virtual void notifyInferiorShutdownOk(); virtual void notifyInferiorShutdownOk();
virtual void notifyInferiorShutdownFailed(); virtual void notifyInferiorShutdownFailed();
+27 -3
View File
@@ -52,8 +52,10 @@
#include <utils/checkablemessagebox.h> #include <utils/checkablemessagebox.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/portlist.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <qmldebug/qmldebugcommandlinearguments.h> #include <qmldebug/qmldebugcommandlinearguments.h>
@@ -126,9 +128,7 @@ void DebuggerRunTool::start()
if (rp.startMode == StartInternal if (rp.startMode == StartInternal
&& rp.inferior.executable.isEmpty() && rp.inferior.executable.isEmpty()
&& rp.interpreter.isEmpty()) { && rp.interpreter.isEmpty()) {
appendMessage(tr("No executable specified.") + QLatin1Char('\n'), ErrorMessageFormat); reportFailure(tr("No executable specified.") + '\n');
runControl()->reportApplicationStart();
runControl()->reportApplicationStop();
return; return;
} }
@@ -177,6 +177,11 @@ void DebuggerRunTool::notifyEngineRemoteSetupFinished(const RemoteSetupResult &r
m_engine->notifyEngineRemoteSetupFinished(result); m_engine->notifyEngineRemoteSetupFinished(result);
} }
void DebuggerRunTool::setRemoteParameters(const RemoteSetupResult &result)
{
m_engine->setRemoteParameters(result);
}
void DebuggerRunTool::stop() void DebuggerRunTool::stop()
{ {
m_engine->quitDebugger(); m_engine->quitDebugger();
@@ -202,6 +207,11 @@ DebuggerStartParameters &DebuggerRunTool::startParameters()
return m_engine->runParameters(); return m_engine->runParameters();
} }
int DebuggerRunTool::portsUsedByDebugger() const
{
return isCppDebugging() + isQmlDebugging();
}
void DebuggerRunTool::notifyInferiorIll() void DebuggerRunTool::notifyInferiorIll()
{ {
m_engine->notifyInferiorIll(); m_engine->notifyInferiorIll();
@@ -510,6 +520,12 @@ void DebuggerRunTool::setStartParameters(const DebuggerStartParameters &sp, QStr
void DebuggerRunTool::setRunParameters(const DebuggerRunParameters &rp, QString *errorMessage) void DebuggerRunTool::setRunParameters(const DebuggerRunParameters &rp, QString *errorMessage)
{ {
int portsUsed = portsUsedByDebugger();
if (portsUsed > device()->freePorts().count()) {
*errorMessage = tr("Cannot debug: Not enough free ports available.");
return;
}
DebuggerRunParameters m_rp = rp; DebuggerRunParameters m_rp = rp;
runControl()->setDisplayName(m_rp.displayName); runControl()->setDisplayName(m_rp.displayName);
@@ -540,6 +556,14 @@ void DebuggerRunTool::setRunParameters(const DebuggerRunParameters &rp, QString
m_engine->setRunTool(this); m_engine->setRunTool(this);
} }
void DebuggerRunTool::appendSolibSearchPath(const QString &str)
{
QString path = str;
DebuggerStartParameters &sp = startParameters();
path.replace("%{sysroot}", sp.sysRoot);
sp.solibSearchPath.append(path);
}
DebuggerRunTool::~DebuggerRunTool() DebuggerRunTool::~DebuggerRunTool()
{ {
disconnect(); disconnect();
@@ -69,6 +69,7 @@ public:
void startFailed(); void startFailed();
void notifyEngineRemoteServerRunning(const QByteArray &msg, int pid); void notifyEngineRemoteServerRunning(const QByteArray &msg, int pid);
void notifyEngineRemoteSetupFinished(const RemoteSetupResult &result); void notifyEngineRemoteSetupFinished(const RemoteSetupResult &result);
void setRemoteParameters(const RemoteSetupResult &result);
void notifyInferiorIll(); void notifyInferiorIll();
Q_SLOT void notifyInferiorExited(); Q_SLOT void notifyInferiorExited();
void quitDebugger(); void quitDebugger();
@@ -79,6 +80,10 @@ public:
bool isCppDebugging() const { return m_isCppDebugging; } bool isCppDebugging() const { return m_isCppDebugging; }
bool isQmlDebugging() const { return m_isQmlDebugging; } bool isQmlDebugging() const { return m_isQmlDebugging; }
int portsUsedByDebugger() const;
virtual void doRemoteSetup() { emit requestRemoteSetup(); }
void appendSolibSearchPath(const QString &str);
signals: signals:
void stateChanged(Debugger::DebuggerState state); void stateChanged(Debugger::DebuggerState state);
+144 -74
View File
@@ -60,6 +60,8 @@
using namespace Utils; using namespace Utils;
using namespace ProjectExplorer::Internal; using namespace ProjectExplorer::Internal;
const bool debugStates = false;
namespace ProjectExplorer { namespace ProjectExplorer {
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@@ -522,7 +524,7 @@ public:
~RunControlPrivate() ~RunControlPrivate()
{ {
QTC_CHECK(state == State::Stopped); QTC_CHECK(state == State::Stopped || state == State::Initialized);
delete targetRunner; delete targetRunner;
delete toolRunner; delete toolRunner;
delete outputFormatter; delete outputFormatter;
@@ -544,6 +546,9 @@ public:
void checkState(State expectedState); void checkState(State expectedState);
void setState(State state); void setState(State state);
void debugMessage(const QString &msg);
QString stateName(State s) const;
void initiateStart(); void initiateStart();
void onTargetPrepared(); void onTargetPrepared();
@@ -560,10 +565,17 @@ public:
void initiateStop(); void initiateStop();
void onToolStopped(); void onToolStopped();
void onToolStopFailed(const QString &msg);
void onTargetStopped(); void onTargetStopped();
void onTargetStopFailed(const QString &msg);
void onToolFailed(const QString &msg); void onToolFailed(const QString &msg);
void onToolSuccess();
void onTargetFailed(const QString &msg); void onTargetFailed(const QString &msg);
void onTargetSuccess();
void handleFailure(); void handleFailure();
void showError(const QString &msg); void showError(const QString &msg);
@@ -659,14 +671,16 @@ void RunControlPrivate::initiateStart()
{ {
checkState(State::Initialized); checkState(State::Initialized);
setState(State::TargetPreparing); setState(State::TargetPreparing);
targetRunner->prepare(); debugMessage("Queue: Prepare target runner");
QTimer::singleShot(0, targetRunner, &TargetRunner::prepare);
} }
void RunControlPrivate::onTargetPrepared() void RunControlPrivate::onTargetPrepared()
{ {
checkState(State::TargetPreparing); checkState(State::TargetPreparing);
setState(State::ToolPreparing); setState(State::ToolPreparing);
toolRunner->prepare(); debugMessage("Queue: Prepare tool runner");
QTimer::singleShot(0, toolRunner, &ToolRunner::prepare);
} }
void RunControlPrivate::onTargetPrepareFailed(const QString &msg) void RunControlPrivate::onTargetPrepareFailed(const QString &msg)
@@ -681,7 +695,8 @@ void RunControlPrivate::onToolPrepared()
{ {
checkState(State::ToolPreparing); checkState(State::ToolPreparing);
setState(State::TargetStarting); setState(State::TargetStarting);
targetRunner->start(); debugMessage("Queue: Start target runner");
QTimer::singleShot(0, targetRunner, &TargetRunner::start);
} }
void RunControlPrivate::onToolPrepareFailed(const QString &msg) void RunControlPrivate::onToolPrepareFailed(const QString &msg)
@@ -696,7 +711,8 @@ void RunControlPrivate::onTargetStarted()
{ {
checkState(State::TargetStarting); checkState(State::TargetStarting);
setState(State::ToolStarting); setState(State::ToolStarting);
toolRunner->start(); debugMessage("Queue: Start tool runner");
QTimer::singleShot(0, toolRunner, &ToolRunner::start);
} }
void RunControlPrivate::onTargetStartFailed(const QString &msg) void RunControlPrivate::onTargetStartFailed(const QString &msg)
@@ -725,54 +741,109 @@ void RunControlPrivate::initiateStop()
{ {
checkState(State::Running); checkState(State::Running);
setState(State::ToolStopping); setState(State::ToolStopping);
toolRunner->stop(); debugMessage("Queue: Stop tool runner");
QTimer::singleShot(0, toolRunner, &ToolRunner::stop);
} }
void RunControlPrivate::onToolStopped() void RunControlPrivate::onToolStopped()
{ {
toolRunner->onStop(); toolRunner->onStop();
debugMessage("Tool stopped");
checkState(State::ToolStopping); checkState(State::ToolStopping);
setState(State::TargetStopping); setState(State::TargetStopping);
targetRunner->stop(); debugMessage("Queue: Stop target runner");
QTimer::singleShot(0, targetRunner, &TargetRunner::stop);
}
void RunControlPrivate::onToolStopFailed(const QString &msg)
{
checkState(State::ToolStopping);
targetRunner->onToolFailure();
debugMessage("Tool stop failed");
showError(msg);
setState(State::Stopped);
} }
void RunControlPrivate::onTargetStopped() void RunControlPrivate::onTargetStopped()
{ {
targetRunner->onStop();
debugMessage("Target stopped");
checkState(State::TargetStopping); checkState(State::TargetStopping);
setState(State::Stopped); setState(State::Stopped);
QTC_CHECK(applicationProcessHandle.isValid()); }
q->setApplicationProcessHandle(Utils::ProcessHandle());
toolRunner->onFinished(); void RunControlPrivate::onTargetStopFailed(const QString &msg)
targetRunner->onFinished(); {
debugMessage("Target stop failed");
checkState(State::TargetStopping);
toolRunner->onTargetFailure();
showError(msg);
setState(State::Stopped);
} }
void RunControlPrivate::onTargetFailed(const QString &msg) void RunControlPrivate::onTargetFailed(const QString &msg)
{ {
debugMessage("Target operation failed");
if (state == State::TargetPreparing) { if (state == State::TargetPreparing) {
onTargetPrepareFailed(msg); onTargetPrepareFailed(msg);
} else if (state == State::TargetStarting) { } else if (state == State::TargetStarting) {
onTargetStartFailed(msg); onTargetStartFailed(msg);
} else if (state == State::TargetStopping) {
onTargetStopFailed(msg);
} else { } else {
showError(msg); showError(msg);
// showError(RunControl::tr("Unexpected state: %1").arg(int(state))); showError(RunControl::tr("Unexpected state: %1").arg(int(state)));
setState(State::Stopped);
}
}
void RunControlPrivate::onTargetSuccess()
{
debugMessage("Target operation successful");
if (state == State::TargetPreparing) {
onTargetPrepared();
} else if (state == State::TargetStarting) {
onTargetStarted();
} else if (state == State::TargetStopping) {
onTargetStopped();
} else {
showError(RunControl::tr("Unexpected state: %1").arg(int(state)));
setState(State::Stopped); setState(State::Stopped);
} }
} }
void RunControlPrivate::onToolFailed(const QString &msg) void RunControlPrivate::onToolFailed(const QString &msg)
{ {
debugMessage("Tool operation failed");
if (state == State::ToolPreparing) { if (state == State::ToolPreparing) {
onToolPrepareFailed(msg); onToolPrepareFailed(msg);
} else if (state == State::ToolStarting) { } else if (state == State::ToolStarting) {
onToolStartFailed(msg); onToolStartFailed(msg);
} else if (state == State::ToolStopping) {
onToolStartFailed(msg);
} else { } else {
showError(msg); showError(msg);
// showError(RunControl::tr("Unexpected state: %1").arg(int(state))); showError(RunControl::tr("Unexpected state: %1").arg(int(state)));
setState(State::Stopped); setState(State::Stopped);
} }
} }
void RunControlPrivate::onToolSuccess()
{
debugMessage("Tool operation successful");
if (state == State::ToolPreparing) {
onToolPrepared();
} else if (state == State::ToolStarting) {
onToolStarted();
} else if (state == State::ToolStopping) {
onToolStopped();
} else {
showError(RunControl::tr("Unexpected state: %1").arg(int(state)));
setState(State::Stopped);
}
}
void RunControlPrivate::handleFailure() void RunControlPrivate::handleFailure()
{ {
switch (state) { switch (state) {
@@ -1028,6 +1099,24 @@ void RunControlPrivate::checkState(State expectedState)
qDebug() << "Unexpected state " << expectedState << " have: " << state; qDebug() << "Unexpected state " << expectedState << " have: " << state;
} }
QString RunControlPrivate::stateName(State s) const
{
# define SN(x) case x: return QLatin1String(#x);
switch (s) {
SN(State::Initialized)
SN(State::TargetPreparing)
SN(State::ToolPreparing)
SN(State::TargetStarting)
SN(State::ToolStarting)
SN(State::Running)
SN(State::ToolStopping)
SN(State::TargetStopping)
SN(State::Stopped)
}
return QLatin1String("<unknown>");
# undef SN
}
void RunControlPrivate::setState(State newState) void RunControlPrivate::setState(State newState)
{ {
if (!isAllowedTransition(state, newState)) if (!isAllowedTransition(state, newState))
@@ -1035,20 +1124,32 @@ void RunControlPrivate::setState(State newState)
state = newState; state = newState;
debugMessage("Entering state " + stateName(newState));
// Extra reporting. // Extra reporting.
switch (state) { switch (state) {
case State::Running: case State::Running:
emit q->started(); emit q->started();
break; break;
case State::Stopped: case State::Stopped:
emit q->finished(); QTC_CHECK(applicationProcessHandle.isValid());
q->setApplicationProcessHandle(Utils::ProcessHandle());
toolRunner->onFinished();
targetRunner->onFinished();
state = State::Initialized; // Reset for potential re-running. state = State::Initialized; // Reset for potential re-running.
emit q->finished();
break; break;
default: default:
break; break;
} }
} }
void RunControlPrivate::debugMessage(const QString &msg)
{
if (debugStates)
q->appendMessage(msg + '\n', Utils::DebugFormat);
}
/*! /*!
Brings the application determined by this RunControl's \c applicationProcessHandle Brings the application determined by this RunControl's \c applicationProcessHandle
to the foreground. to the foreground.
@@ -1079,8 +1180,7 @@ void RunControl::reportApplicationStop()
// multiple times. Fix it there and then add a soft assert here. // multiple times. Fix it there and then add a soft assert here.
return; return;
} }
d->onToolStopped(); d->onTargetStopped();
emit finished();
} }
void RunControl::bringApplicationToForegroundInternal() void RunControl::bringApplicationToForegroundInternal()
@@ -1145,9 +1245,9 @@ void SimpleTargetRunner::start()
QTC_ASSERT(r.is<StandardRunnable>(), return); QTC_ASSERT(r.is<StandardRunnable>(), return);
const QString executable = r.as<StandardRunnable>().executable; const QString executable = r.as<StandardRunnable>().executable;
if (executable.isEmpty()) { if (executable.isEmpty()) {
reportStartFailed(RunControl::tr("No executable specified.")); reportFailure(RunControl::tr("No executable specified."));
} else if (!QFileInfo::exists(executable)) { } else if (!QFileInfo::exists(executable)) {
reportStartFailed(RunControl::tr("Executable %1 does not exist.") reportFailure(RunControl::tr("Executable %1 does not exist.")
.arg(QDir::toNativeSeparators(executable))); .arg(QDir::toNativeSeparators(executable)));
} else { } else {
QString msg = RunControl::tr("Starting %1...").arg(QDir::toNativeSeparators(executable)) + '\n'; QString msg = RunControl::tr("Starting %1...").arg(QDir::toNativeSeparators(executable)) + '\n';
@@ -1173,7 +1273,7 @@ void SimpleTargetRunner::start()
connect(&m_launcher, &ApplicationLauncher::finished, connect(&m_launcher, &ApplicationLauncher::finished,
this, [this] { this, [this] {
m_launcher.disconnect(this); m_launcher.disconnect(this);
reportStopped(); reportSuccess();
}); });
connect(&m_launcher, &ApplicationLauncher::reportProgress, connect(&m_launcher, &ApplicationLauncher::reportProgress,
@@ -1195,7 +1295,7 @@ void SimpleTargetRunner::onProcessStarted()
// Console processes only know their pid after being started // Console processes only know their pid after being started
runControl()->setApplicationProcessHandle(m_launcher.applicationPID()); runControl()->setApplicationProcessHandle(m_launcher.applicationPID());
runControl()->bringApplicationToForeground(); runControl()->bringApplicationToForeground();
reportStarted(); reportSuccess();
} }
void SimpleTargetRunner::onProcessFinished(int exitCode, QProcess::ExitStatus status) void SimpleTargetRunner::onProcessFinished(int exitCode, QProcess::ExitStatus status)
@@ -1219,6 +1319,10 @@ TargetRunner::TargetRunner(RunControl *runControl)
runControl->setTargetRunner(this); runControl->setTargetRunner(this);
} }
TargetRunner::~TargetRunner()
{
}
RunControl *TargetRunner::runControl() const RunControl *TargetRunner::runControl() const
{ {
return m_runControl; return m_runControl;
@@ -1236,48 +1340,29 @@ IDevice::ConstPtr TargetRunner::device() const
void TargetRunner::prepare() void TargetRunner::prepare()
{ {
reportPrepared(); // By default nothing to do, all is fine. reportSuccess(); // By default nothing to do, all is fine.
}
void TargetRunner::reportPrepareFailed(const QString &msg)
{
m_runControl->d->onTargetPrepareFailed(msg);
}
void TargetRunner::reportPrepared()
{
QTC_ASSERT(m_runControl, return);
m_runControl->d->onTargetPrepared();
} }
void TargetRunner::start() void TargetRunner::start()
{ {
reportStarted(); reportSuccess();
}
void TargetRunner::reportStartFailed(const QString &msg)
{
m_runControl->d->onTargetStartFailed(msg);
} }
void TargetRunner::stop() void TargetRunner::stop()
{ {
reportStopped(); // By default all is fine. reportSuccess(); // By default all is fine.
}
void TargetRunner::reportStarted()
{
QTC_ASSERT(m_runControl, return);
m_runControl->d->onTargetStarted();
} }
void TargetRunner::reportStopped() void TargetRunner::reportStopped()
{ {
QTC_ASSERT(m_runControl, return);
onStop();
m_runControl->d->onTargetStopped(); m_runControl->d->onTargetStopped();
} }
void TargetRunner::reportSuccess()
{
m_runControl->d->onTargetSuccess();
}
void TargetRunner::reportFailure(const QString &msg) void TargetRunner::reportFailure(const QString &msg)
{ {
m_runControl->d->onTargetFailed(msg); m_runControl->d->onTargetFailed(msg);
@@ -1292,6 +1377,10 @@ ToolRunner::ToolRunner(RunControl *runControl)
runControl->setToolRunner(this); runControl->setToolRunner(this);
} }
ToolRunner::~ToolRunner()
{
}
RunControl *ToolRunner::runControl() const RunControl *ToolRunner::runControl() const
{ {
return m_runControl; return m_runControl;
@@ -1319,41 +1408,17 @@ const Connection &ToolRunner::connection() const
void ToolRunner::prepare() void ToolRunner::prepare()
{ {
reportPrepared(); reportSuccess();
}
void ToolRunner::reportPrepared()
{
m_runControl->d->onToolPrepared();
} }
void ToolRunner::start() void ToolRunner::start()
{ {
reportStarted(); reportSuccess();
}
void ToolRunner::reportStartFailed(const QString &msg)
{
QTC_CHECK(m_runControl->d->state == RunControlPrivate::State::ToolStarting);
m_runControl->d->targetRunner->onToolFailure();
reportFailure(msg);
}
void ToolRunner::reportStarted()
{
m_runControl->d->onToolStarted();
} }
void ToolRunner::stop() void ToolRunner::stop()
{ {
reportStopped(); reportSuccess();
}
void ToolRunner::reportStopFailed(const QString &msg)
{
QTC_CHECK(m_runControl->d->state == RunControlPrivate::State::ToolStopping);
m_runControl->d->targetRunner->onToolFailure();
reportFailure(msg);
} }
void ToolRunner::reportStopped() void ToolRunner::reportStopped()
@@ -1361,6 +1426,11 @@ void ToolRunner::reportStopped()
m_runControl->d->onToolStopped(); m_runControl->d->onToolStopped();
} }
void ToolRunner::reportSuccess()
{
m_runControl->d->onToolSuccess();
}
void ToolRunner::reportFailure(const QString &msg) void ToolRunner::reportFailure(const QString &msg)
{ {
m_runControl->d->onToolFailed(msg); m_runControl->d->onToolFailed(msg);
+12 -18
View File
@@ -454,6 +454,7 @@ class PROJECTEXPLORER_EXPORT TargetRunner : public QObject
public: public:
explicit TargetRunner(RunControl *runControl); explicit TargetRunner(RunControl *runControl);
~TargetRunner() override;
RunControl *runControl() const; RunControl *runControl() const;
void appendMessage(const QString &msg, Utils::OutputFormat format); void appendMessage(const QString &msg, Utils::OutputFormat format);
@@ -461,20 +462,16 @@ public:
// Preparation phase. // Preparation phase.
virtual void prepare(); // Initiate setup. Needs to report result. virtual void prepare(); // Initiate setup. Needs to report result.
void reportPrepareFailed(const QString &msg = QString());
void reportPrepared();
// Startup phase. // Startup phase.
virtual void start(); // Initiates start. Needs to report result. virtual void start(); // Initiates start. Needs to report result.
void reportStartFailed(const QString &msg = QString());
void reportStarted();
// Stopping phase. // Stopping phase.
virtual void stop(); // Initiates stop. Needs to report result. virtual void stop(); // Initiates stop. Needs to report result.
void reportStopFailed(const QString &msg = QString());
void reportStopped();
// Generic error in uncertain state. //
void reportStopped();
// Generic success report, proceed to next stage.
void reportSuccess();
// Generic error, start ramp down.
void reportFailure(const QString &msg = QString()); void reportFailure(const QString &msg = QString());
// Customization points. No reporting required nor wanted. // Customization points. No reporting required nor wanted.
@@ -497,6 +494,7 @@ class PROJECTEXPLORER_EXPORT ToolRunner : public QObject
public: public:
explicit ToolRunner(RunControl *runControl); explicit ToolRunner(RunControl *runControl);
~ToolRunner() override;
RunControl *runControl() const; RunControl *runControl() const;
@@ -508,20 +506,16 @@ public:
// Preparation phase. // Preparation phase.
virtual void prepare(); // Initiates preparation, needs to report success or failure. virtual void prepare(); // Initiates preparation, needs to report success or failure.
void reportPrepareFailed(const QString &msg = QString());
void reportPrepared();
// Start phase. // Start phase.
virtual void start(); virtual void start();
void reportStartFailed(const QString &msg = QString());
void reportStarted();
// Stop phase. // Stop phase.
virtual void stop(); virtual void stop();
void reportStopFailed(const QString &msg = QString());
void reportStopped();
// Generic error in uncertain state. //
void reportStopped();
// Generic success report, proceed to next stage.
void reportSuccess();
// Generic error, start ramp down.
void reportFailure(const QString &msg = QString()); void reportFailure(const QString &msg = QString());
// Customization points. No reporting required nor wanted. // Customization points. No reporting required nor wanted.
@@ -34,6 +34,7 @@
#include <utils/portlist.h> #include <utils/portlist.h>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils;
namespace RemoteLinux { namespace RemoteLinux {
namespace Internal { namespace Internal {
@@ -42,11 +43,11 @@ class AbstractRemoteLinuxRunSupportPrivate
{ {
public: public:
ApplicationLauncher launcher; ApplicationLauncher launcher;
AbstractRemoteLinuxRunSupport::State state = AbstractRemoteLinuxRunSupport::Inactive;
DeviceUsedPortsGatherer portsGatherer; DeviceUsedPortsGatherer portsGatherer;
ApplicationLauncher fifoCreator; ApplicationLauncher fifoCreator;
Utils::PortList portList; PortList portList;
QString fifo; QString fifo;
bool usesFifo = false;
}; };
} // namespace Internal } // namespace Internal
@@ -61,7 +62,6 @@ AbstractRemoteLinuxRunSupport::AbstractRemoteLinuxRunSupport(RunControl *runCont
AbstractRemoteLinuxRunSupport::~AbstractRemoteLinuxRunSupport() AbstractRemoteLinuxRunSupport::~AbstractRemoteLinuxRunSupport()
{ {
setFinished();
delete d; delete d;
} }
@@ -70,42 +70,12 @@ ApplicationLauncher *AbstractRemoteLinuxRunSupport::applicationLauncher()
return &d->launcher; return &d->launcher;
} }
void AbstractRemoteLinuxRunSupport::setState(AbstractRemoteLinuxRunSupport::State state) void AbstractRemoteLinuxRunSupport::setUsesFifo(bool on)
{ {
d->state = state; d->usesFifo = on;
} }
AbstractRemoteLinuxRunSupport::State AbstractRemoteLinuxRunSupport::state() const Port AbstractRemoteLinuxRunSupport::findPort() const
{
return d->state;
}
void AbstractRemoteLinuxRunSupport::handleResourcesError(const QString &message)
{
QTC_ASSERT(d->state == GatheringResources, return);
setFinished();
reset();
emit adapterSetupFailed(message);
}
void AbstractRemoteLinuxRunSupport::handleResourcesAvailable()
{
QTC_ASSERT(d->state == GatheringResources, return);
d->portList = device()->freePorts();
emit executionStartRequested();
}
void AbstractRemoteLinuxRunSupport::setFinished()
{
if (d->state == Inactive)
return;
if (d->state == Running)
applicationLauncher()->stop();
d->state = Inactive;
}
Utils::Port AbstractRemoteLinuxRunSupport::findPort() const
{ {
return d->portsGatherer.getNextFreePort(&d->portList); return d->portsGatherer.getNextFreePort(&d->portList);
} }
@@ -115,21 +85,31 @@ QString AbstractRemoteLinuxRunSupport::fifo() const
return d->fifo; return d->fifo;
} }
void AbstractRemoteLinuxRunSupport::prepare()
{
if (d->usesFifo)
createRemoteFifo();
else
startPortsGathering();
}
void AbstractRemoteLinuxRunSupport::startPortsGathering() void AbstractRemoteLinuxRunSupport::startPortsGathering()
{ {
QTC_ASSERT(d->state == Inactive, return); appendMessage(tr("Checking available ports...") + '\n', NormalMessageFormat);
d->state = GatheringResources; connect(&d->portsGatherer, &DeviceUsedPortsGatherer::error, this, [&](const QString &msg) {
connect(&d->portsGatherer, &DeviceUsedPortsGatherer::error, reportFailure(msg);
this, &AbstractRemoteLinuxRunSupport::handleResourcesError); });
connect(&d->portsGatherer, &DeviceUsedPortsGatherer::portListReady, connect(&d->portsGatherer, &DeviceUsedPortsGatherer::portListReady, this, [&] {
this, &AbstractRemoteLinuxRunSupport::handleResourcesAvailable); d->portList = device()->freePorts();
//appendMessage(tr("Found %1 free ports").arg(d->portList.count()), NormalMessageFormat);
reportSuccess();
});
d->portsGatherer.start(device()); d->portsGatherer.start(device());
} }
void AbstractRemoteLinuxRunSupport::createRemoteFifo() void AbstractRemoteLinuxRunSupport::createRemoteFifo()
{ {
QTC_ASSERT(d->state == Inactive, return); appendMessage(tr("Creating remote socket...") + '\n', NormalMessageFormat);
d->state = GatheringResources;
StandardRunnable r; StandardRunnable r;
r.executable = QLatin1String("/bin/sh"); r.executable = QLatin1String("/bin/sh");
@@ -143,10 +123,11 @@ void AbstractRemoteLinuxRunSupport::createRemoteFifo()
connect(&d->fifoCreator, &ApplicationLauncher::finished, connect(&d->fifoCreator, &ApplicationLauncher::finished,
this, [this, output, errors](bool success) { this, [this, output, errors](bool success) {
if (!success) { if (!success) {
handleResourcesError(QString("Failed to create fifo: %1").arg(QLatin1String(*errors))); reportFailure(QString("Failed to create fifo: %1").arg(QLatin1String(*errors)));
} else { } else {
d->fifo = QString::fromLatin1(*output); d->fifo = QString::fromLatin1(*output);
handleResourcesAvailable(); //appendMessage(tr("Created fifo").arg(d->fifo), NormalMessageFormat);
reportSuccess();
} }
}); });
@@ -163,11 +144,53 @@ void AbstractRemoteLinuxRunSupport::createRemoteFifo()
d->fifoCreator.start(r, device()); d->fifoCreator.start(r, device());
} }
void AbstractRemoteLinuxRunSupport::reset() void AbstractRemoteLinuxRunSupport::start()
{ {
connect(&d->launcher, &ApplicationLauncher::remoteStderr,
this, &AbstractRemoteLinuxRunSupport::handleRemoteErrorOutput);
connect(&d->launcher, &ApplicationLauncher::remoteStdout,
this, &AbstractRemoteLinuxRunSupport::handleRemoteOutput);
connect(&d->launcher, &ApplicationLauncher::finished,
this, &AbstractRemoteLinuxRunSupport::handleAppRunnerFinished);
connect(&d->launcher, &ApplicationLauncher::reportProgress,
this, &AbstractRemoteLinuxRunSupport::handleProgressReport);
connect(&d->launcher, &ApplicationLauncher::reportError,
this, &AbstractRemoteLinuxRunSupport::handleAppRunnerError);
connect(&d->launcher, &ApplicationLauncher::remoteProcessStarted,
this, &TargetRunner::reportSuccess);
d->launcher.start(runControl()->runnable(), device());
}
void AbstractRemoteLinuxRunSupport::onFinished()
{
d->launcher.disconnect(this);
d->launcher.stop();
d->portsGatherer.disconnect(this); d->portsGatherer.disconnect(this);
applicationLauncher()->disconnect(this); }
d->state = Inactive;
void AbstractRemoteLinuxRunSupport::handleAppRunnerFinished(bool success)
{
success ? reportStopped() : reportFailure();
}
void AbstractRemoteLinuxRunSupport::handleAppRunnerError(const QString &error)
{
reportFailure(error);
}
void AbstractRemoteLinuxRunSupport::handleRemoteOutput(const QByteArray &output)
{
appendMessage(QString::fromUtf8(output), StdOutFormat);
}
void AbstractRemoteLinuxRunSupport::handleRemoteErrorOutput(const QByteArray &output)
{
appendMessage(QString::fromUtf8(output), StdErrFormat);
}
void AbstractRemoteLinuxRunSupport::handleProgressReport(const QString &progressOutput)
{
appendMessage(progressOutput + '\n', LogMessageFormat);
} }
} // namespace RemoteLinux } // namespace RemoteLinux
@@ -41,39 +41,30 @@ class REMOTELINUX_EXPORT AbstractRemoteLinuxRunSupport : public ProjectExplorer:
Q_OBJECT Q_OBJECT
public: public:
enum State
{
Inactive,
GatheringResources,
StartingRunner,
Running
};
explicit AbstractRemoteLinuxRunSupport(ProjectExplorer::RunControl *runControl); explicit AbstractRemoteLinuxRunSupport(ProjectExplorer::RunControl *runControl);
~AbstractRemoteLinuxRunSupport(); ~AbstractRemoteLinuxRunSupport();
ProjectExplorer::ApplicationLauncher *applicationLauncher(); ProjectExplorer::ApplicationLauncher *applicationLauncher();
void setState(State state); void setUsesFifo(bool on);
State state() const;
void setFinished();
void startPortsGathering();
Utils::Port findPort() const; Utils::Port findPort() const;
void createRemoteFifo();
QString fifo() const; QString fifo() const;
void reset();
signals:
void adapterSetupFailed(const QString &error);
void executionStartRequested();
private: private:
void handleResourcesError(const QString &message); void prepare() override;
void handleResourcesAvailable(); void start() override;
void onFinished() override;
void createRemoteFifo();
void startPortsGathering();
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 handleAdapterSetupDone();
Internal::AbstractRemoteLinuxRunSupportPrivate * const d; Internal::AbstractRemoteLinuxRunSupportPrivate * const d;
}; };
@@ -53,16 +53,17 @@ class RemoteLinuxAnalyzeSupportPrivate
public: public:
RemoteLinuxAnalyzeSupportPrivate(RunControl *runControl) RemoteLinuxAnalyzeSupportPrivate(RunControl *runControl)
{ {
if (runControl->runMode() != ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) if (runControl->runMode() == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
return; usesFifo = true;
RunConfiguration *runConfiguration = runControl->runConfiguration(); RunConfiguration *runConfiguration = runControl->runConfiguration();
QTC_ASSERT(runConfiguration, return); QTC_ASSERT(runConfiguration, return);
IRunConfigurationAspect *perfAspect = IRunConfigurationAspect *perfAspect =
runConfiguration->extraAspect("Analyzer.Perf.Settings"); runConfiguration->extraAspect("Analyzer.Perf.Settings");
QTC_ASSERT(perfAspect, return); QTC_ASSERT(perfAspect, return);
perfRecordArguments = perfRecordArguments =
perfAspect->currentSettings()->property("perfRecordArguments").toStringList() perfAspect->currentSettings()->property("perfRecordArguments").toStringList()
.join(' '); .join(' ');
}
} }
Utils::Port qmlPort; Utils::Port qmlPort;
@@ -71,6 +72,7 @@ public:
ApplicationLauncher outputGatherer; ApplicationLauncher outputGatherer;
QmlDebug::QmlOutputParser outputParser; QmlDebug::QmlOutputParser outputParser;
bool usesFifo = false;
}; };
} // namespace Internal } // namespace Internal
@@ -81,19 +83,9 @@ RemoteLinuxAnalyzeSupport::RemoteLinuxAnalyzeSupport(RunControl *runControl)
: ToolRunner(runControl), : ToolRunner(runControl),
d(new RemoteLinuxAnalyzeSupportPrivate(runControl)) d(new RemoteLinuxAnalyzeSupportPrivate(runControl))
{ {
connect(runControl, &RunControl::starting,
this, &RemoteLinuxAnalyzeSupport::handleRemoteSetupRequested);
connect(&d->outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort, connect(&d->outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
this, &RemoteLinuxAnalyzeSupport::remoteIsRunning); this, &RemoteLinuxAnalyzeSupport::remoteIsRunning);
connect(runControl, &RunControl::finished, targetRunner()->setUsesFifo(runControl->runMode() == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE);
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() RemoteLinuxAnalyzeSupport::~RemoteLinuxAnalyzeSupport()
@@ -103,48 +95,27 @@ RemoteLinuxAnalyzeSupport::~RemoteLinuxAnalyzeSupport()
void RemoteLinuxAnalyzeSupport::showMessage(const QString &msg, Utils::OutputFormat format) void RemoteLinuxAnalyzeSupport::showMessage(const QString &msg, Utils::OutputFormat format)
{ {
if (targetRunner()->state() != AbstractRemoteLinuxRunSupport::Inactive) appendMessage(msg, format);
appendMessage(msg, format);
d->outputParser.processOutput(msg); d->outputParser.processOutput(msg);
} }
void RemoteLinuxAnalyzeSupport::handleRemoteSetupRequested() void RemoteLinuxAnalyzeSupport::start()
{ {
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);
targetRunner()->startPortsGathering();
} else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
showMessage(tr("Creating remote socket...") + QLatin1Char('\n'),
Utils::NormalMessageFormat);
targetRunner()->createRemoteFifo();
}
}
void RemoteLinuxAnalyzeSupport::startExecution()
{
QTC_ASSERT(targetRunner()->state() == AbstractRemoteLinuxRunSupport::GatheringResources, return);
const Core::Id runMode = runControl()->runMode(); const Core::Id runMode = runControl()->runMode();
if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { if (runMode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) {
d->qmlPort = targetRunner()->findPort(); d->qmlPort = targetRunner()->findPort();
if (!d->qmlPort.isValid()) { if (!d->qmlPort.isValid()) {
handleAdapterSetupFailed(tr("Not enough free ports on device for profiling.")); reportFailure(tr("Not enough free ports on device for profiling."));
return; return;
} }
} else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) { } else if (runMode == ProjectExplorer::Constants::PERFPROFILER_RUN_MODE) {
d->remoteFifo = targetRunner()->fifo(); d->remoteFifo = targetRunner()->fifo();
if (d->remoteFifo.isEmpty()) { if (d->remoteFifo.isEmpty()) {
handleAdapterSetupFailed(tr("FIFO for profiling data could not be created.")); reportFailure(tr("FIFO for profiling data could not be created."));
return; return;
} }
} }
targetRunner()->setState(AbstractRemoteLinuxRunSupport::StartingRunner);
ApplicationLauncher *runner = targetRunner()->applicationLauncher(); ApplicationLauncher *runner = targetRunner()->applicationLauncher();
connect(runner, &ApplicationLauncher::remoteStderr, connect(runner, &ApplicationLauncher::remoteStderr,
this, &RemoteLinuxAnalyzeSupport::handleRemoteErrorOutput); this, &RemoteLinuxAnalyzeSupport::handleRemoteErrorOutput);
@@ -190,26 +161,18 @@ void RemoteLinuxAnalyzeSupport::startExecution()
void RemoteLinuxAnalyzeSupport::handleAppRunnerError(const QString &error) void RemoteLinuxAnalyzeSupport::handleAppRunnerError(const QString &error)
{ {
if (targetRunner()->state() == AbstractRemoteLinuxRunSupport::Running) showMessage(error, Utils::ErrorMessageFormat);
showMessage(error, Utils::ErrorMessageFormat); reportFailure(error);
else if (targetRunner()->state() != AbstractRemoteLinuxRunSupport::Inactive)
handleAdapterSetupFailed(error);
} }
void RemoteLinuxAnalyzeSupport::handleAppRunnerFinished(bool success) void RemoteLinuxAnalyzeSupport::handleAppRunnerFinished(bool success)
{ {
// reset needs to be called first to ensure that the correct state is set. // reset needs to be called first to ensure that the correct state is set.
targetRunner()->reset();
if (!success) if (!success)
showMessage(tr("Failure running remote process."), Utils::NormalMessageFormat); showMessage(tr("Failure running remote process."), Utils::NormalMessageFormat);
runControl()->notifyRemoteFinished(); runControl()->notifyRemoteFinished();
} }
void RemoteLinuxAnalyzeSupport::handleProfilingFinished()
{
targetRunner()->setFinished();
}
void RemoteLinuxAnalyzeSupport::remoteIsRunning() void RemoteLinuxAnalyzeSupport::remoteIsRunning()
{ {
runControl()->notifyRemoteSetupDone(d->qmlPort); runControl()->notifyRemoteSetupDone(d->qmlPort);
@@ -222,16 +185,11 @@ AbstractRemoteLinuxRunSupport *RemoteLinuxAnalyzeSupport::targetRunner() const
void RemoteLinuxAnalyzeSupport::handleRemoteOutput(const QByteArray &output) void RemoteLinuxAnalyzeSupport::handleRemoteOutput(const QByteArray &output)
{ {
QTC_ASSERT(targetRunner()->state() == AbstractRemoteLinuxRunSupport::Inactive
|| targetRunner()->state() == AbstractRemoteLinuxRunSupport::Running, return);
showMessage(QString::fromUtf8(output), Utils::StdOutFormat); showMessage(QString::fromUtf8(output), Utils::StdOutFormat);
} }
void RemoteLinuxAnalyzeSupport::handleRemoteErrorOutput(const QByteArray &output) void RemoteLinuxAnalyzeSupport::handleRemoteErrorOutput(const QByteArray &output)
{ {
QTC_ASSERT(targetRunner()->state() != AbstractRemoteLinuxRunSupport::GatheringResources, return);
showMessage(QString::fromUtf8(output), Utils::StdErrFormat); showMessage(QString::fromUtf8(output), Utils::StdErrFormat);
} }
@@ -247,9 +205,6 @@ void RemoteLinuxAnalyzeSupport::handleAdapterSetupFailed(const QString &error)
void RemoteLinuxAnalyzeSupport::handleRemoteProcessStarted() void RemoteLinuxAnalyzeSupport::handleRemoteProcessStarted()
{ {
QTC_ASSERT(targetRunner()->state() == AbstractRemoteLinuxRunSupport::StartingRunner, return);
targetRunner()->setState(AbstractRemoteLinuxRunSupport::Running);
} }
} // namespace RemoteLinux } // namespace RemoteLinux
@@ -44,7 +44,7 @@ public:
~RemoteLinuxAnalyzeSupport() override; ~RemoteLinuxAnalyzeSupport() override;
private: private:
void startExecution(); void start() override;
void handleAdapterSetupFailed(const QString &error); void handleAdapterSetupFailed(const QString &error);
void handleRemoteSetupRequested(); void handleRemoteSetupRequested();
@@ -55,7 +55,6 @@ private:
void handleProgressReport(const QString &progressOutput); void handleProgressReport(const QString &progressOutput);
void handleRemoteProcessStarted(); void handleRemoteProcessStarted();
void handleProfilingFinished();
void remoteIsRunning(); void remoteIsRunning();
AbstractRemoteLinuxRunSupport *targetRunner() const; AbstractRemoteLinuxRunSupport *targetRunner() const;
@@ -25,10 +25,10 @@
#include "remotelinuxdebugsupport.h" #include "remotelinuxdebugsupport.h"
#include "remotelinuxcustomrunconfiguration.h"
#include "remotelinuxrunconfiguration.h" #include "remotelinuxrunconfiguration.h"
#include <debugger/debuggerruncontrol.h> #include <debugger/debuggerruncontrol.h>
#include <debugger/debuggerstartparameters.h>
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
@@ -41,109 +41,87 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <QPointer>
using namespace QSsh;
using namespace Debugger; using namespace Debugger;
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
namespace RemoteLinux { namespace RemoteLinux {
namespace Internal {
class LinuxDeviceDebugSupportPrivate LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl, QString *errorMessage)
: DebuggerRunTool(runControl)
{ {
public: RunConfiguration *runConfig = runControl->runConfiguration();
QByteArray gdbserverOutput;
Port gdbServerPort;
Port qmlPort;
};
} // namespace Internal QString symbolFile;
if (auto rlrc = qobject_cast<RemoteLinuxRunConfiguration *>(runConfig))
symbolFile = rlrc->localExecutableFilePath();
if (auto rlrc = qobject_cast<Internal::RemoteLinuxCustomRunConfiguration *>(runConfig))
symbolFile = rlrc->localExecutableFilePath();
if (symbolFile.isEmpty()) {
*errorMessage = tr("Cannot debug: Local executable is not set.");
return;
}
using namespace Internal; DebuggerStartParameters params;
params.startMode = AttachToRemoteServer;
params.closeMode = KillAndExitMonitorAtClose;
params.remoteSetupNeeded = false;
LinuxDeviceDebugSupport::LinuxDeviceDebugSupport(RunControl *runControl, if (isQmlDebugging()) {
const Debugger::DebuggerStartParameters &sp, params.qmlServer.host = device()->sshParameters().host;
QString *errorMessage) params.qmlServer.port = Utils::Port(); // port is selected later on
: DebuggerRunTool(runControl, sp, errorMessage), }
d(new LinuxDeviceDebugSupportPrivate) if (isCppDebugging()) {
{ Runnable r = runnable();
connect(this, &DebuggerRunTool::requestRemoteSetup, QTC_ASSERT(r.is<StandardRunnable>(), return);
this, &LinuxDeviceDebugSupport::handleRemoteSetupRequested); auto stdRunnable = r.as<StandardRunnable>();
connect(runControl, &RunControl::finished, params.useExtendedRemote = true;
this, &LinuxDeviceDebugSupport::handleDebuggingFinished); params.inferior.executable = stdRunnable.executable;
params.inferior.commandLineArguments = stdRunnable.commandLineArguments;
if (isQmlDebugging()) {
params.inferior.commandLineArguments.prepend(' ');
params.inferior.commandLineArguments.prepend(
QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices));
}
params.remoteChannel = device()->sshParameters().host + ":-1";
params.symbolFile = symbolFile;
}
connect(qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl->targetRunner()), setStartParameters(params);
&AbstractRemoteLinuxRunSupport::executionStartRequested,
this, &LinuxDeviceDebugSupport::startExecution);
connect(qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl->targetRunner()),
&AbstractRemoteLinuxRunSupport::adapterSetupFailed,
this, &LinuxDeviceDebugSupport::handleAdapterSetupFailed);
} }
LinuxDeviceDebugSupport::~LinuxDeviceDebugSupport() LinuxDeviceDebugSupport::~LinuxDeviceDebugSupport()
{ {
delete d;
} }
AbstractRemoteLinuxRunSupport *LinuxDeviceDebugSupport::targetRunner() const void LinuxDeviceDebugSupport::prepare()
{ {
return qobject_cast<AbstractRemoteLinuxRunSupport *>(runControl()->targetRunner()); auto targetRunner = 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() == AbstractRemoteLinuxRunSupport::Inactive, return);
showMessage(tr("Checking available ports...") + QLatin1Char('\n'), LogStatus);
targetRunner()->startPortsGathering();
}
void LinuxDeviceDebugSupport::startExecution()
{
QTC_ASSERT(state() == AbstractRemoteLinuxRunSupport::GatheringResources, return);
if (isCppDebugging()) { if (isCppDebugging()) {
d->gdbServerPort = targetRunner()->findPort(); m_gdbServerPort = targetRunner->findPort();
if (!d->gdbServerPort.isValid()) { if (!m_gdbServerPort.isValid()) {
handleAdapterSetupFailed(tr("Not enough free ports on device for C++ debugging.")); reportFailure(tr("Not enough free ports on device for C++ debugging."));
return; return;
} }
} }
if (isQmlDebugging()) { if (isQmlDebugging()) {
d->qmlPort = targetRunner()->findPort(); m_qmlPort = targetRunner->findPort();
if (!d->qmlPort.isValid()) { if (!m_qmlPort.isValid()) {
handleAdapterSetupFailed(tr("Not enough free ports on device for QML debugging.")); reportFailure(tr("Not enough free ports on device for QML debugging."));
return; return;
} }
} }
targetRunner()->setState(AbstractRemoteLinuxRunSupport::StartingRunner); runControl()->setRunnable(realRunnable());
d->gdbserverOutput.clear();
ApplicationLauncher *launcher = targetRunner()->applicationLauncher(); RemoteSetupResult result;
connect(launcher, &ApplicationLauncher::remoteStderr, result.success = true;
this, &LinuxDeviceDebugSupport::handleRemoteErrorOutput); result.gdbServerPort = m_gdbServerPort;
connect(launcher, &ApplicationLauncher::remoteStdout, result.qmlServerPort = m_qmlPort;
this, &LinuxDeviceDebugSupport::handleRemoteOutput); setRemoteParameters(result);
connect(launcher, &ApplicationLauncher::finished,
this, &LinuxDeviceDebugSupport::handleAppRunnerFinished);
connect(launcher, &ApplicationLauncher::reportProgress,
this, &LinuxDeviceDebugSupport::handleProgressReport);
connect(launcher, &ApplicationLauncher::reportError,
this, &LinuxDeviceDebugSupport::handleAppRunnerError);
if (isQmlDebugging() && !isCppDebugging())
connect(launcher, &ApplicationLauncher::remoteProcessStarted,
this, &LinuxDeviceDebugSupport::handleRemoteProcessStarted);
launcher->start(realRunnable(), device()); DebuggerRunTool::prepare();
} }
Runnable LinuxDeviceDebugSupport::realRunnable() const Runnable LinuxDeviceDebugSupport::realRunnable() const
@@ -153,7 +131,7 @@ Runnable LinuxDeviceDebugSupport::realRunnable() const
QString command; QString command;
if (isQmlDebugging()) if (isQmlDebugging())
args.prepend(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices, d->qmlPort)); args.prepend(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices, m_qmlPort));
if (isQmlDebugging() && !isCppDebugging()) { if (isQmlDebugging() && !isCppDebugging()) {
command = r.executable; command = r.executable;
@@ -163,102 +141,11 @@ Runnable LinuxDeviceDebugSupport::realRunnable() const
command = QLatin1String("gdbserver"); command = QLatin1String("gdbserver");
args.clear(); args.clear();
args.append(QString::fromLatin1("--multi")); args.append(QString::fromLatin1("--multi"));
args.append(QString::fromLatin1(":%1").arg(d->gdbServerPort.number())); args.append(QString::fromLatin1(":%1").arg(m_gdbServerPort.number()));
} }
r.executable = command; r.executable = command;
r.commandLineArguments = QtcProcess::joinArgs(args, OsTypeLinux); r.commandLineArguments = QtcProcess::joinArgs(args, OsTypeLinux);
return r; return r;
} }
void LinuxDeviceDebugSupport::handleAppRunnerError(const QString &error)
{
if (state() == AbstractRemoteLinuxRunSupport::Running) {
showMessage(error, AppError);
notifyInferiorIll();
} else if (state() != AbstractRemoteLinuxRunSupport::Inactive) {
handleAdapterSetupFailed(error);
}
}
void LinuxDeviceDebugSupport::handleAppRunnerFinished(bool success)
{
if (state() == AbstractRemoteLinuxRunSupport::Inactive)
return;
if (state() == AbstractRemoteLinuxRunSupport::Running) {
// The QML engine does not realize on its own that the application has finished.
if (isQmlDebugging() && !isCppDebugging())
quitDebugger();
else if (!success)
notifyInferiorIll();
} else if (state() == AbstractRemoteLinuxRunSupport::StartingRunner) {
RemoteSetupResult result;
result.success = false;
result.reason = tr("Debugging failed.");
notifyEngineRemoteSetupFinished(result);
}
targetRunner()->reset();
}
void LinuxDeviceDebugSupport::handleDebuggingFinished()
{
targetRunner()->setFinished();
targetRunner()->reset();
}
void LinuxDeviceDebugSupport::handleRemoteOutput(const QByteArray &output)
{
QTC_ASSERT(state() == AbstractRemoteLinuxRunSupport::Inactive
|| state() == AbstractRemoteLinuxRunSupport::Running, return);
showMessage(QString::fromUtf8(output), AppOutput);
}
void LinuxDeviceDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
{
QTC_ASSERT(state() != AbstractRemoteLinuxRunSupport::GatheringResources, return);
showMessage(QString::fromUtf8(output), AppError);
if (state() == AbstractRemoteLinuxRunSupport::StartingRunner && isCppDebugging()) {
d->gdbserverOutput += output;
if (d->gdbserverOutput.contains("Listening on port")) {
handleAdapterSetupDone();
d->gdbserverOutput.clear();
}
}
}
void LinuxDeviceDebugSupport::handleProgressReport(const QString &progressOutput)
{
showMessage(progressOutput + QLatin1Char('\n'), LogStatus);
}
void LinuxDeviceDebugSupport::handleAdapterSetupFailed(const QString &error)
{
RemoteSetupResult result;
result.success = false;
result.reason = tr("Initial setup failed: %1").arg(error);
notifyEngineRemoteSetupFinished(result);
}
void LinuxDeviceDebugSupport::handleAdapterSetupDone()
{
targetRunner()->setState(AbstractRemoteLinuxRunSupport::Running);
RemoteSetupResult result;
result.success = true;
result.gdbServerPort = d->gdbServerPort;
result.qmlServerPort = d->qmlPort;
notifyEngineRemoteSetupFinished(result);
}
void LinuxDeviceDebugSupport::handleRemoteProcessStarted()
{
QTC_ASSERT(isQmlDebugging() && !isCppDebugging(), return);
QTC_ASSERT(state() == AbstractRemoteLinuxRunSupport::StartingRunner, return);
handleAdapterSetupDone();
}
} // namespace RemoteLinux } // namespace RemoteLinux
@@ -31,15 +31,12 @@
namespace RemoteLinux { namespace RemoteLinux {
namespace Internal { class LinuxDeviceDebugSupportPrivate; }
class REMOTELINUX_EXPORT LinuxDeviceDebugSupport : public Debugger::DebuggerRunTool class REMOTELINUX_EXPORT LinuxDeviceDebugSupport : public Debugger::DebuggerRunTool
{ {
Q_OBJECT Q_OBJECT
public: public:
LinuxDeviceDebugSupport(ProjectExplorer::RunControl *runControl, LinuxDeviceDebugSupport(ProjectExplorer::RunControl *runControl,
const Debugger::DebuggerStartParameters &sp,
QString *errorMessage = nullptr); QString *errorMessage = nullptr);
~LinuxDeviceDebugSupport() override; ~LinuxDeviceDebugSupport() override;
@@ -47,24 +44,10 @@ protected:
virtual ProjectExplorer::Runnable realRunnable() const; virtual ProjectExplorer::Runnable realRunnable() const;
private: private:
void startExecution(); void prepare() override;
void handleAdapterSetupFailed(const QString &error);
void handleRemoteSetupRequested(); Utils::Port m_gdbServerPort;
void handleAppRunnerError(const QString &error); Utils::Port m_qmlPort;
void handleRemoteOutput(const QByteArray &output);
void handleRemoteErrorOutput(const QByteArray &output);
void handleAppRunnerFinished(bool success);
void handleProgressReport(const QString &progressOutput);
void handleRemoteProcessStarted();
void handleAdapterSetupDone();
void handleDebuggingFinished();
AbstractRemoteLinuxRunSupport *targetRunner() const;
AbstractRemoteLinuxRunSupport::State state() const;
Internal::LinuxDeviceDebugSupportPrivate * const d;
}; };
} // namespace RemoteLinux } // namespace RemoteLinux
@@ -41,7 +41,6 @@
#include <projectexplorer/runnables.h> #include <projectexplorer/runnables.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
#include <utils/portlist.h> #include <utils/portlist.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -68,7 +67,6 @@ bool RemoteLinuxRunControlFactory::canRun(RunConfiguration *runConfiguration, Co
} }
const Core::Id id = runConfiguration->id(); const Core::Id id = runConfiguration->id();
QTC_ASSERT(runConfiguration->extraAspect<DebuggerRunConfigurationAspect>(), return false);
return runConfiguration->isEnabled() return runConfiguration->isEnabled()
&& (id == RemoteLinuxCustomRunConfiguration::runConfigId() && (id == RemoteLinuxCustomRunConfiguration::runConfigId()
|| id.name().startsWith(RemoteLinuxRunConfiguration::IdPrefix)); || id.name().startsWith(RemoteLinuxRunConfiguration::IdPrefix));
@@ -81,65 +79,15 @@ RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, Co
if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) { if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) {
auto runControl = new RunControl(runConfig, mode); auto runControl = new RunControl(runConfig, mode);
(void) new SimpleTargetRunner(runControl); (void) new AbstractRemoteLinuxRunSupport(runControl);
return runControl; return runControl;
} }
const auto rcRunnable = runConfig->runnable();
QTC_ASSERT(rcRunnable.is<StandardRunnable>(), return 0);
const auto stdRunnable = rcRunnable.as<StandardRunnable>();
if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE
|| mode == ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN) { || mode == ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN) {
IDevice::ConstPtr dev = DeviceKitInformation::device(runConfig->target()->kit());
if (!dev) {
*errorMessage = tr("Cannot debug: Kit has no device.");
return 0;
}
auto aspect = runConfig->extraAspect<DebuggerRunConfigurationAspect>();
QTC_ASSERT(aspect, return 0);
int portsUsed = aspect->portsUsedByDebugger();
if (portsUsed > dev->freePorts().count()) {
*errorMessage = tr("Cannot debug: Not enough free ports available.");
return 0;
}
QString symbolFile;
if (auto rlrc = qobject_cast<RemoteLinuxRunConfiguration *>(runConfig))
symbolFile = rlrc->localExecutableFilePath();
if (auto rlrc = qobject_cast<RemoteLinuxCustomRunConfiguration *>(runConfig))
symbolFile = rlrc->localExecutableFilePath();
if (symbolFile.isEmpty()) {
*errorMessage = tr("Cannot debug: Local executable is not set.");
return 0;
}
DebuggerStartParameters params;
params.startMode = AttachToRemoteServer;
params.closeMode = KillAndExitMonitorAtClose;
params.remoteSetupNeeded = true;
if (aspect->useQmlDebugger()) {
params.qmlServer.host = dev->sshParameters().host;
params.qmlServer.port = Utils::Port(); // port is selected later on
}
if (aspect->useCppDebugger()) {
params.useExtendedRemote = true;
params.inferior.executable = stdRunnable.executable;
params.inferior.commandLineArguments = stdRunnable.commandLineArguments;
if (aspect->useQmlDebugger()) {
params.inferior.commandLineArguments.prepend(QLatin1Char(' '));
params.inferior.commandLineArguments.prepend(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices));
}
params.remoteChannel = dev->sshParameters().host + QLatin1String(":-1");
params.symbolFile = symbolFile;
}
auto runControl = new RunControl(runConfig, mode); auto runControl = new RunControl(runConfig, mode);
(void) new AbstractRemoteLinuxRunSupport(runControl); (void) new AbstractRemoteLinuxRunSupport(runControl);
(void) new LinuxDeviceDebugSupport(runControl, params, errorMessage); (void) new LinuxDeviceDebugSupport(runControl, errorMessage);
return runControl; return runControl;
} }
+2 -2
View File
@@ -102,7 +102,7 @@ void ValgrindToolRunner::start()
return; return;
} }
reportStarted(); reportSuccess();
} }
void ValgrindToolRunner::stop() void ValgrindToolRunner::stop()
@@ -160,7 +160,7 @@ void ValgrindToolRunner::runnerFinished()
disconnect(runner(), &ValgrindRunner::finished, disconnect(runner(), &ValgrindRunner::finished,
this, &ValgrindToolRunner::runnerFinished); this, &ValgrindToolRunner::runnerFinished);
reportStopped(); reportSuccess();
} }
void ValgrindToolRunner::receiveProcessOutput(const QString &output, OutputFormat format) void ValgrindToolRunner::receiveProcessOutput(const QString &output, OutputFormat format)