forked from qt-creator/qt-creator
BareMetal: Force use of a separate RunWorker in StartupOnNetwork mode
This insures the server runs before gdb starts up and tries to connect. Change-Id: Idd4863d32f8c0e25bbbec6bdd4e52b8576fc1b6a Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -55,12 +55,25 @@ namespace Internal {
|
||||
|
||||
BareMetalDebugSupport::BareMetalDebugSupport(RunControl *runControl)
|
||||
: Debugger::DebuggerRunTool(runControl)
|
||||
, m_appLauncher(new ProjectExplorer::ApplicationLauncher(this))
|
||||
{}
|
||||
|
||||
BareMetalDebugSupport::~BareMetalDebugSupport()
|
||||
{
|
||||
setFinished();
|
||||
auto dev = qSharedPointerCast<const BareMetalDevice>(device());
|
||||
if (!dev) {
|
||||
reportFailure(tr("Cannot debug: Kit has no device."));
|
||||
return;
|
||||
}
|
||||
|
||||
const GdbServerProvider *p = GdbServerProviderManager::findProvider(dev->gdbServerProviderId());
|
||||
if (p->startupMode() == GdbServerProvider::StartupOnNetwork) {
|
||||
StandardRunnable r;
|
||||
r.executable = p->executable();
|
||||
// We need to wrap the command arguments depending on a host OS,
|
||||
// as the bare metal's GDB servers are launched on a host,
|
||||
// but not on a target.
|
||||
r.commandLineArguments = Utils::QtcProcess::joinArgs(p->arguments(), Utils::HostOsInfo::hostOs());
|
||||
m_gdbServer = new SimpleTargetRunner(runControl);
|
||||
m_gdbServer->setRunnable(r);
|
||||
addDependency(m_gdbServer);
|
||||
}
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::start()
|
||||
@@ -81,20 +94,10 @@ void BareMetalDebugSupport::start()
|
||||
const Target *target = rc->target();
|
||||
QTC_ASSERT(target, reportFailure(); return);
|
||||
|
||||
const Kit *kit = target->kit();
|
||||
QTC_ASSERT(kit, reportFailure(); return);
|
||||
|
||||
auto dev = qSharedPointerCast<const BareMetalDevice>(DeviceKitInformation::device(kit));
|
||||
if (!dev) {
|
||||
reportFailure(tr("Cannot debug: Kit has no device."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto dev = qSharedPointerCast<const BareMetalDevice>(device());
|
||||
QTC_ASSERT(dev, reportFailure(); return);
|
||||
const GdbServerProvider *p = GdbServerProviderManager::findProvider(dev->gdbServerProviderId());
|
||||
if (!p) {
|
||||
reportFailure(tr("Cannot debug: Device has no GDB server provider configuration."));
|
||||
return;
|
||||
}
|
||||
QTC_ASSERT(p, reportFailure(); return);
|
||||
|
||||
Debugger::DebuggerStartParameters sp;
|
||||
|
||||
@@ -119,114 +122,8 @@ void BareMetalDebugSupport::start()
|
||||
|
||||
setStartParameters(sp);
|
||||
|
||||
connect(runControl(), &RunControl::finished,
|
||||
this, &BareMetalDebugSupport::debuggingFinished);
|
||||
|
||||
if (p->startupMode() == GdbServerProvider::StartupOnNetwork) {
|
||||
m_state = StartingRunner;
|
||||
showMessage(tr("Starting GDB server...") + '\n', Debugger::LogStatus);
|
||||
|
||||
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::remoteStderr,
|
||||
this, &BareMetalDebugSupport::remoteErrorOutputMessage);
|
||||
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::remoteStdout,
|
||||
this, &BareMetalDebugSupport::remoteOutputMessage);
|
||||
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::remoteProcessStarted,
|
||||
this, &BareMetalDebugSupport::remoteProcessStarted);
|
||||
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::finished,
|
||||
this, &BareMetalDebugSupport::appRunnerFinished);
|
||||
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::reportProgress,
|
||||
this, &BareMetalDebugSupport::progressReport);
|
||||
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::reportError,
|
||||
this, &BareMetalDebugSupport::appRunnerError);
|
||||
|
||||
StandardRunnable r;
|
||||
r.executable = p->executable();
|
||||
// We need to wrap the command arguments depending on a host OS,
|
||||
// as the bare metal's GDB servers are launched on a host,
|
||||
// but not on a target.
|
||||
r.commandLineArguments = Utils::QtcProcess::joinArgs(p->arguments(), Utils::HostOsInfo::hostOs());
|
||||
m_appLauncher->start(r, dev);
|
||||
}
|
||||
|
||||
DebuggerRunTool::start();
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::debuggingFinished()
|
||||
{
|
||||
setFinished();
|
||||
reset();
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::remoteOutputMessage(const QByteArray &output)
|
||||
{
|
||||
QTC_ASSERT(m_state == Inactive || m_state == Running, return);
|
||||
showMessage(QString::fromUtf8(output), Debugger::AppOutput);
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::remoteErrorOutputMessage(const QByteArray &output)
|
||||
{
|
||||
QTC_ASSERT(m_state == Inactive, return);
|
||||
showMessage(QString::fromUtf8(output), Debugger::AppError);
|
||||
|
||||
// FIXME: Should we here parse an outputn?
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::remoteProcessStarted()
|
||||
{
|
||||
QTC_ASSERT(m_state == StartingRunner, return);
|
||||
m_state = Running;
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::appRunnerFinished(bool success)
|
||||
{
|
||||
if (m_state == Inactive)
|
||||
return;
|
||||
|
||||
if (m_state == Running) {
|
||||
if (!success)
|
||||
notifyInferiorIll();
|
||||
} else if (m_state == StartingRunner) {
|
||||
reportFailure(tr("Debugging failed."));
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::progressReport(const QString &progressOutput)
|
||||
{
|
||||
showMessage(progressOutput + QLatin1Char('\n'), Debugger::LogStatus);
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::appRunnerError(const QString &error)
|
||||
{
|
||||
if (m_state == Running) {
|
||||
showMessage(error, Debugger::AppError);
|
||||
notifyInferiorIll();
|
||||
} else if (m_state != Inactive) {
|
||||
adapterSetupFailed(error);
|
||||
}
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::adapterSetupFailed(const QString &error)
|
||||
{
|
||||
debuggingFinished();
|
||||
reportFailure(tr("Initial setup failed: %1").arg(error));
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::setFinished()
|
||||
{
|
||||
if (m_state == Inactive)
|
||||
return;
|
||||
if (m_state == Running)
|
||||
m_appLauncher->stop();
|
||||
m_state = Inactive;
|
||||
}
|
||||
|
||||
void BareMetalDebugSupport::reset()
|
||||
{
|
||||
m_appLauncher->disconnect(this);
|
||||
m_state = Inactive;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
|
@@ -27,8 +27,6 @@
|
||||
|
||||
#include <debugger/debuggerruncontrol.h>
|
||||
|
||||
namespace ProjectExplorer { class ApplicationLauncher; }
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
@@ -38,29 +36,11 @@ class BareMetalDebugSupport : public Debugger::DebuggerRunTool
|
||||
|
||||
public:
|
||||
BareMetalDebugSupport(ProjectExplorer::RunControl *runControl);
|
||||
~BareMetalDebugSupport();
|
||||
|
||||
private:
|
||||
enum State { Inactive, StartingRunner, Running };
|
||||
|
||||
void start() override;
|
||||
|
||||
void debuggingFinished();
|
||||
void remoteOutputMessage(const QByteArray &output);
|
||||
void remoteErrorOutputMessage(const QByteArray &output);
|
||||
void remoteProcessStarted();
|
||||
void appRunnerFinished(bool success);
|
||||
void progressReport(const QString &progressOutput);
|
||||
void appRunnerError(const QString &error);
|
||||
|
||||
void adapterSetupFailed(const QString &error);
|
||||
|
||||
void startExecution();
|
||||
void setFinished();
|
||||
void reset();
|
||||
|
||||
ProjectExplorer::ApplicationLauncher *m_appLauncher;
|
||||
State m_state = Inactive;
|
||||
ProjectExplorer::SimpleTargetRunner *m_gdbServer = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
Reference in New Issue
Block a user