forked from qt-creator/qt-creator
fix shutdown paths
this includes: - move the gdb ownership back to the engine (thus strip down the adaptors as far as possible) - make gdb startup synchronous - make adapter shutdown synchronous - fix the state transitions relating to shutdown
This commit is contained in:
@@ -824,6 +824,9 @@ void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG6
|
||||
void CdbDebugEngine::processTerminated(unsigned long exitCode)
|
||||
{
|
||||
manager()->showDebuggerOutput(LogMisc, tr("The process exited with exit code %1.").arg(exitCode));
|
||||
if (m_engine->state() != InferiorStopping)
|
||||
setState(InferiorStopping, Q_FUNC_INFO, __LINE__);
|
||||
setState(InferiorStopped, Q_FUNC_INFO, __LINE__);
|
||||
setState(InferiorShuttingDown, Q_FUNC_INFO, __LINE__);
|
||||
m_d->setDebuggeeHandles(0, 0);
|
||||
m_d->clearForRun();
|
||||
@@ -919,14 +922,11 @@ void CdbDebugEnginePrivate::endDebugging(EndDebuggingMode em)
|
||||
errorMessage.clear();
|
||||
}
|
||||
// Clean up resources (open files, etc.)
|
||||
m_engine->setState(AdapterShuttingDown, Q_FUNC_INFO, __LINE__);
|
||||
m_engine->setState(EngineShuttingDown, Q_FUNC_INFO, __LINE__);
|
||||
clearForRun();
|
||||
const HRESULT hr = m_cif.debugClient->EndSession(DEBUG_END_PASSIVE);
|
||||
if (SUCCEEDED(hr)) {
|
||||
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
|
||||
} else {
|
||||
m_engine->setState(AdapterShutdownFailed, Q_FUNC_INFO, __LINE__);
|
||||
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
|
||||
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
errorMessage = QString::fromLatin1("There were errors trying to end debugging: %1").arg(msgComFailed("EndSession", hr));
|
||||
manager()->showDebuggerOutput(LogError, errorMessage);
|
||||
}
|
||||
|
@@ -79,15 +79,13 @@ enum DebuggerState
|
||||
|
||||
InferiorStopping, // Debuggee running, stop requested
|
||||
InferiorStopped, // Debuggee stopped
|
||||
InferiorStopFailed, // Debuggee stopped
|
||||
InferiorStopFailed, // Debuggee not stopped, will kill debugger
|
||||
|
||||
InferiorShuttingDown,
|
||||
InferiorShutDown,
|
||||
InferiorShutdownFailed,
|
||||
|
||||
AdapterShuttingDown,
|
||||
//AdapterShutDown, // Use DebuggerNotReady instead
|
||||
AdapterShutdownFailed,
|
||||
EngineShuttingDown
|
||||
};
|
||||
|
||||
enum DebuggerStartMode
|
||||
|
@@ -101,43 +101,35 @@
|
||||
// gdbserver, the trk client etc are referred to as 'Adapter',
|
||||
// whereas the debugged process is referred to as 'Inferior'.
|
||||
//
|
||||
// 0 == DebuggerNotReady
|
||||
// 0 == DebuggerNotReady
|
||||
// |
|
||||
// EngineStarting
|
||||
// EngineStarting
|
||||
// |
|
||||
// AdapterStarting --> AdapterStartFailed --> 0
|
||||
// AdapterStarting --> AdapterStartFailed --> 0
|
||||
// |
|
||||
// AdapterStarted
|
||||
// |
|
||||
// InferiorStarting --> InferiorStartFailed --> 0
|
||||
// |
|
||||
// (core) | (attach) (remote)
|
||||
// .-----------------<-|->--------------------.
|
||||
// | v |
|
||||
// InferiorUnrunnable | |
|
||||
// | | v
|
||||
// | | (plain)
|
||||
// | | (trk)
|
||||
// | |
|
||||
// | | .------------------------------------.
|
||||
// | | v |
|
||||
// | InferiorRunningRequested v |
|
||||
// | | | |
|
||||
// | .---- InferiorRunning | |
|
||||
// | | | | |
|
||||
// | | InferiorStopping | |
|
||||
// | | | | |
|
||||
// | v v | |
|
||||
// | |<--- InferiorStopped <-----------' |
|
||||
// | | | |
|
||||
// | | `---------------------------------------'
|
||||
// | |
|
||||
// | '---> InferiorShuttingDown -> InferiorShutdownFailed
|
||||
// | |
|
||||
// | InferiorShutDown
|
||||
// | |
|
||||
// | v
|
||||
// '------------> AdapterShuttingDown -> AdapterShutdownFailed --> 0
|
||||
// AdapterStarted ------------------------------------.
|
||||
// | v
|
||||
// InferiorStarting ----> InferiorStartFailed -------->|
|
||||
// | |
|
||||
// (core) | (attach) (term) (remote) |
|
||||
// .-----------------<-|->------------------. |
|
||||
// | v | |
|
||||
// InferiorUnrunnable | (plain) | |
|
||||
// | | (trk) | |
|
||||
// | | | |
|
||||
// | .--> InferiorRunningRequested | |
|
||||
// | | | | |
|
||||
// | | InferiorRunning | |
|
||||
// | | | | |
|
||||
// | | InferiorStopping | |
|
||||
// | | | | |
|
||||
// | '------ InferiorStopped <-----------' |
|
||||
// | | v
|
||||
// | InferiorShuttingDown -> InferiorShutdownFailed ---->|
|
||||
// | | |
|
||||
// | InferiorShutDown |
|
||||
// | | |
|
||||
// '--------> EngineShuttingDown <--------------------------------'
|
||||
// |
|
||||
// 0
|
||||
//
|
||||
@@ -208,8 +200,7 @@ static const char *stateName(int s)
|
||||
SN(InferiorShuttingDown)
|
||||
SN(InferiorShutDown)
|
||||
SN(InferiorShutdownFailed)
|
||||
SN(AdapterShuttingDown)
|
||||
SN(AdapterShutdownFailed)
|
||||
SN(EngineShuttingDown)
|
||||
}
|
||||
return "<unknown>";
|
||||
#undef SN
|
||||
@@ -1574,7 +1565,7 @@ static bool isAllowedTransition(int from, int to)
|
||||
case AdapterStarting:
|
||||
return to == AdapterStarted || to == AdapterStartFailed;
|
||||
case AdapterStarted:
|
||||
return to == InferiorStarting;
|
||||
return to == InferiorStarting || to == EngineShuttingDown;
|
||||
case AdapterStartFailed:
|
||||
return to == DebuggerNotReady;
|
||||
|
||||
@@ -1582,37 +1573,38 @@ static bool isAllowedTransition(int from, int to)
|
||||
return to == InferiorRunningRequested || to == InferiorStopped
|
||||
|| to == InferiorStartFailed || to == InferiorUnrunnable;
|
||||
case InferiorStartFailed:
|
||||
return to == DebuggerNotReady;
|
||||
return to == EngineShuttingDown;
|
||||
|
||||
case InferiorRunningRequested:
|
||||
return to == InferiorRunning;
|
||||
case InferiorRunning:
|
||||
return to == InferiorStopping || to == InferiorShuttingDown;
|
||||
return to == InferiorStopping;
|
||||
|
||||
case InferiorStopping:
|
||||
return to == InferiorStopped || to == InferiorStopFailed;
|
||||
case InferiorStopped:
|
||||
return to == InferiorRunningRequested || to == InferiorShuttingDown;
|
||||
case InferiorStopFailed:
|
||||
return to == DebuggerNotReady;
|
||||
return to == EngineShuttingDown;
|
||||
|
||||
case InferiorUnrunnable:
|
||||
return to == AdapterShuttingDown;
|
||||
return to == EngineShuttingDown;
|
||||
case InferiorShuttingDown:
|
||||
return to == InferiorShutDown || to == InferiorShutdownFailed;
|
||||
case InferiorShutDown:
|
||||
return to == AdapterShuttingDown;
|
||||
return to == EngineShuttingDown;
|
||||
case InferiorShutdownFailed:
|
||||
return to == EngineShuttingDown;
|
||||
|
||||
case AdapterShuttingDown:
|
||||
case EngineShuttingDown:
|
||||
return to == DebuggerNotReady;
|
||||
|
||||
default:
|
||||
qDebug() << "UNKNOWN STATE: " << from;
|
||||
}
|
||||
|
||||
qDebug() << "UNKNOWN STATE:" << from;
|
||||
return false;
|
||||
}
|
||||
|
||||
void DebuggerManager::setState(DebuggerState state)
|
||||
void DebuggerManager::setState(DebuggerState state, bool forced)
|
||||
{
|
||||
//STATE_DEBUG("STATUS CHANGE: FROM " << stateName(d->m_state)
|
||||
// << " TO " << stateName(state));
|
||||
@@ -1621,7 +1613,7 @@ void DebuggerManager::setState(DebuggerState state)
|
||||
.arg(stateName(d->m_state)).arg(d->m_state).arg(stateName(state)).arg(state);
|
||||
//if (!((d->m_state == -1 && state == 0) || (d->m_state == 0 && state == 0)))
|
||||
// qDebug() << msg;
|
||||
if (!isAllowedTransition(d->m_state, state))
|
||||
if (!forced && !isAllowedTransition(d->m_state, state))
|
||||
qDebug() << "UNEXPECTED STATE TRANSITION: " << msg;
|
||||
|
||||
showDebuggerOutput(LogDebug, msg);
|
||||
@@ -1715,8 +1707,7 @@ bool DebuggerManager::debuggerActionsEnabled() const
|
||||
case InferiorShuttingDown:
|
||||
case InferiorShutDown:
|
||||
case InferiorShutdownFailed:
|
||||
case AdapterShuttingDown:
|
||||
case AdapterShutdownFailed:
|
||||
case EngineShuttingDown:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
@@ -1793,9 +1784,9 @@ DebuggerState IDebuggerEngine::state() const
|
||||
return m_manager->state();
|
||||
}
|
||||
|
||||
void IDebuggerEngine::setState(DebuggerState state)
|
||||
void IDebuggerEngine::setState(DebuggerState state, bool forced)
|
||||
{
|
||||
m_manager->setState(state);
|
||||
m_manager->setState(state, forced);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@@ -285,7 +285,7 @@ private:
|
||||
|
||||
void cleanupViews();
|
||||
|
||||
void setState(DebuggerState state);
|
||||
void setState(DebuggerState state, bool forced = false);
|
||||
|
||||
//
|
||||
// internal implementation
|
||||
|
@@ -47,35 +47,18 @@ AbstractGdbAdapter::~AbstractGdbAdapter()
|
||||
disconnect();
|
||||
}
|
||||
|
||||
// This cannot be in the c'tor, as it would not connect the "virtual" slots
|
||||
void AbstractGdbAdapter::commonInit()
|
||||
void AbstractGdbAdapter::shutdown()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
||||
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(handleGdbError(QProcess::ProcessError)));
|
||||
connect(&m_gdbProc, SIGNAL(started()),
|
||||
this, SLOT(handleGdbStarted()));
|
||||
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
this, SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
|
||||
this, SIGNAL(readyReadStandardOutput()));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
|
||||
this, SIGNAL(readyReadStandardError()));
|
||||
}
|
||||
|
||||
QByteArray AbstractGdbAdapter::readAllStandardOutput()
|
||||
const char *AbstractGdbAdapter::inferiorShutdownCommand() const
|
||||
{
|
||||
return m_gdbProc.readAllStandardOutput();
|
||||
}
|
||||
|
||||
QByteArray AbstractGdbAdapter::readAllStandardError()
|
||||
{
|
||||
return m_gdbProc.readAllStandardError();
|
||||
return "kill";
|
||||
}
|
||||
|
||||
void AbstractGdbAdapter::write(const QByteArray &data)
|
||||
{
|
||||
m_gdbProc.write(data);
|
||||
m_engine->m_gdbProc.write(data);
|
||||
}
|
||||
|
||||
bool AbstractGdbAdapter::isTrkAdapter() const
|
||||
|
@@ -42,7 +42,7 @@ namespace Internal {
|
||||
// debugging and TrkGdbAdapter used for on-device debugging.
|
||||
// In the PlainGdbAdapter case it's just a wrapper around a QProcess running
|
||||
// gdb, in the TrkGdbAdapter case it's the interface to the gdb process in
|
||||
// the whole rfomm/gdb/gdbserver combo.
|
||||
// the whole rfcomm/gdb/gdbserver combo.
|
||||
class AbstractGdbAdapter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -51,34 +51,39 @@ public:
|
||||
AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||
virtual ~AbstractGdbAdapter();
|
||||
|
||||
QByteArray readAllStandardOutput();
|
||||
QByteArray readAllStandardError();
|
||||
virtual void write(const QByteArray &data);
|
||||
virtual bool isTrkAdapter() const; // isUtterlyBrokenAdapter
|
||||
|
||||
virtual void startAdapter() = 0;
|
||||
virtual void startInferior() = 0;
|
||||
virtual void interruptInferior() = 0;
|
||||
virtual void shutdown() = 0;
|
||||
virtual void shutdown();
|
||||
virtual const char *inferiorShutdownCommand() const;
|
||||
|
||||
virtual bool dumpersAvailable() const = 0;
|
||||
|
||||
static QString msgGdbStopFailed(const QString &why);
|
||||
static QString msgInferiorStopFailed(const QString &why);
|
||||
static QString msgAttachedToStoppedInferior();
|
||||
static QString msgInferiorStarted();
|
||||
static QString msgInferiorRunning();
|
||||
static QString msgConnectRemoteServerFailed(const QString &why);
|
||||
|
||||
signals:
|
||||
void adapterStarted();
|
||||
|
||||
// Something went wrong with the adapter *before* adapterStarted() was emitted.
|
||||
// Make sure to clean up everything before emitting this signal.
|
||||
void adapterStartFailed(const QString &msg, const QString &settingsIdHint);
|
||||
void adapterShutDown();
|
||||
void adapterShutdownFailed(const QString &msg);
|
||||
|
||||
// Something went wrong with the adapter *after* adapterStarted() was emitted.
|
||||
// Make sure to clean up everything before emitting this signal.
|
||||
void adapterCrashed(const QString &msg);
|
||||
|
||||
// The adapter is still running just fine, but it failed to acquire a debuggee.
|
||||
void inferiorStartFailed(const QString &msg);
|
||||
void inferiorShutDown();
|
||||
void inferiorShutdownFailed(const QString &msg);
|
||||
|
||||
void readyReadStandardOutput();
|
||||
void readyReadStandardError();
|
||||
|
||||
protected:
|
||||
void commonInit();
|
||||
DebuggerState state() const
|
||||
{ return m_engine->state(); }
|
||||
void setState(DebuggerState state)
|
||||
@@ -90,16 +95,7 @@ protected:
|
||||
void showStatusMessage(const QString &msg) const
|
||||
{ m_engine->showStatusMessage(msg); }
|
||||
|
||||
static QString msgGdbStopFailed(const QString &why);
|
||||
static QString msgInferiorStopFailed(const QString &why);
|
||||
static QString msgAttachedToStoppedInferior();
|
||||
static QString msgInferiorStarted();
|
||||
static QString msgInferiorRunning();
|
||||
static QString msgConnectRemoteServerFailed(const QString &why);
|
||||
|
||||
GdbEngine * const m_engine;
|
||||
|
||||
QProcess m_gdbProc;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -53,7 +53,6 @@ namespace Internal {
|
||||
AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
commonInit();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::startAdapter()
|
||||
@@ -62,27 +61,12 @@ void AttachGdbAdapter::startAdapter()
|
||||
setState(AdapterStarting);
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.prepend(_("mi"));
|
||||
gdbArgs.prepend(_("-i"));
|
||||
if (!m_engine->startGdb())
|
||||
return;
|
||||
|
||||
QString location = theDebuggerStringSetting(GdbLocation);
|
||||
m_gdbProc.start(location, gdbArgs);
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
|
||||
emit adapterCrashed(m_engine->errorMessage(error));
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::startInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
@@ -113,58 +97,5 @@ void AttachGdbAdapter::interruptInferior()
|
||||
debugMessage(_("CANNOT INTERRUPT %1").arg(pid));
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::shutdown()
|
||||
{
|
||||
switch (state()) {
|
||||
|
||||
case InferiorStartFailed:
|
||||
m_engine->postCommand(_("-gdb-exit"));
|
||||
setState(DebuggerNotReady);
|
||||
return;
|
||||
|
||||
case InferiorStopped:
|
||||
setState(InferiorShuttingDown);
|
||||
m_engine->postCommand(_("detach"), CB(handleDetach));
|
||||
return;
|
||||
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
}
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleDetach(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
setState(InferiorShutDown);
|
||||
emit inferiorShutDown();
|
||||
shutdown(); // re-iterate...
|
||||
} else {
|
||||
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorShutdownFailed);
|
||||
emit inferiorShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
|
||||
{
|
||||
debugMessage(_("GDB PROESS FINISHED"));
|
||||
emit adapterShutDown();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
@@ -57,16 +57,10 @@ public:
|
||||
void startAdapter();
|
||||
void startInferior();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
const char *inferiorShutdownCommand() const { return "detach"; }
|
||||
|
||||
private:
|
||||
void handleAttach(const GdbResponse &response);
|
||||
void handleDetach(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleGdbStarted();
|
||||
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -53,7 +53,6 @@ namespace Internal {
|
||||
CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
commonInit();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::startAdapter()
|
||||
@@ -62,27 +61,12 @@ void CoreGdbAdapter::startAdapter()
|
||||
setState(AdapterStarting);
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.prepend(_("mi"));
|
||||
gdbArgs.prepend(_("-i"));
|
||||
if (!m_engine->startGdb())
|
||||
return;
|
||||
|
||||
QString location = theDebuggerStringSetting(GdbLocation);
|
||||
m_gdbProc.start(location, gdbArgs);
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
|
||||
emit adapterCrashed(m_engine->errorMessage(error));
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::startInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
@@ -175,45 +159,12 @@ void CoreGdbAdapter::handleTargetCore2(const GdbResponse &response)
|
||||
// emit inferiorStartFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::interruptInferior()
|
||||
{
|
||||
// A core should never 'run'
|
||||
QTC_ASSERT(false, /**/);
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::shutdown()
|
||||
{
|
||||
switch (state()) {
|
||||
|
||||
case DebuggerNotReady:
|
||||
return;
|
||||
|
||||
case InferiorUnrunnable:
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
}
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
|
||||
{
|
||||
debugMessage(_("GDB PROESS FINISHED"));
|
||||
emit adapterShutDown();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
@@ -57,18 +57,12 @@ public:
|
||||
void startAdapter();
|
||||
void startInferior();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
|
||||
private:
|
||||
void handleTargetCore1(const GdbResponse &response);
|
||||
void handleDetach1(const GdbResponse &response);
|
||||
void handleFileExecAndSymbols(const GdbResponse &response);
|
||||
void handleTargetCore2(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleGdbStarted();
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
|
||||
|
||||
QString m_executable;
|
||||
};
|
||||
|
@@ -105,17 +105,29 @@ namespace Internal {
|
||||
|
||||
static bool stateAcceptsGdbCommands(DebuggerState state)
|
||||
{
|
||||
return state == AdapterStarted
|
||||
|| state == InferiorUnrunnable
|
||||
|| state == InferiorStarting
|
||||
|| state == InferiorRunningRequested
|
||||
|| state == InferiorRunning
|
||||
|| state == InferiorStopping
|
||||
|| state == InferiorStopped
|
||||
|| state == InferiorShuttingDown
|
||||
|| state == InferiorShutDown
|
||||
|| state == AdapterShuttingDown;
|
||||
};
|
||||
switch (state) {
|
||||
case AdapterStarting:
|
||||
case AdapterStarted:
|
||||
case AdapterStartFailed:
|
||||
case InferiorUnrunnable:
|
||||
case InferiorStarting:
|
||||
case InferiorStartFailed:
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunning:
|
||||
case InferiorStopping:
|
||||
case InferiorStopped:
|
||||
case InferiorShuttingDown:
|
||||
case InferiorShutDown:
|
||||
case InferiorShutdownFailed:
|
||||
return true;
|
||||
case DebuggerNotReady:
|
||||
case EngineStarting:
|
||||
case InferiorStopFailed:
|
||||
case EngineShuttingDown:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ¤tToken()
|
||||
{
|
||||
@@ -217,27 +229,13 @@ GdbEngine::~GdbEngine()
|
||||
|
||||
void GdbEngine::connectAdapter()
|
||||
{
|
||||
// Gdb Process interaction
|
||||
connect(m_gdbAdapter, SIGNAL(readyReadStandardOutput()),
|
||||
this, SLOT(readGdbStandardOutput()));
|
||||
connect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(readGdbStandardError()));
|
||||
|
||||
connect(m_gdbAdapter, SIGNAL(adapterStarted()),
|
||||
this, SLOT(handleAdapterStarted()));
|
||||
connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)),
|
||||
this, SLOT(handleAdapterStartFailed(QString,QString)));
|
||||
connect(m_gdbAdapter, SIGNAL(adapterShutDown()),
|
||||
this, SLOT(handleAdapterShutDown()));
|
||||
connect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)),
|
||||
this, SLOT(handleAdapterShutdownFailed(QString)));
|
||||
|
||||
connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
|
||||
this, SLOT(handleInferiorStartFailed(QString)));
|
||||
connect(m_gdbAdapter, SIGNAL(inferiorShutDown()),
|
||||
this, SLOT(handleInferiorShutDown()));
|
||||
connect(m_gdbAdapter, SIGNAL(inferiorShutdownFailed(QString)),
|
||||
this, SLOT(handleInferiorShutdownFailed(QString)));
|
||||
|
||||
connect(m_gdbAdapter, SIGNAL(adapterCrashed(QString)),
|
||||
this, SLOT(handleAdapterCrashed(QString)));
|
||||
@@ -571,7 +569,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
|
||||
void GdbEngine::readGdbStandardError()
|
||||
{
|
||||
qWarning() << "Unexpected gdb stderr:" << m_gdbAdapter->readAllStandardError();
|
||||
qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
|
||||
}
|
||||
|
||||
void GdbEngine::readGdbStandardOutput()
|
||||
@@ -579,7 +577,7 @@ void GdbEngine::readGdbStandardOutput()
|
||||
int newstart = 0;
|
||||
int scan = m_inbuffer.size();
|
||||
|
||||
m_inbuffer.append(m_gdbAdapter->readAllStandardOutput());
|
||||
m_inbuffer.append(m_gdbProc.readAllStandardOutput());
|
||||
|
||||
while (newstart < m_inbuffer.size()) {
|
||||
int start = newstart;
|
||||
@@ -1366,8 +1364,73 @@ QString GdbEngine::fullName(const QStringList &candidates)
|
||||
void GdbEngine::shutdown()
|
||||
{
|
||||
debugMessage(_("INITIATE GDBENGINE SHUTDOWN"));
|
||||
initializeVariables();
|
||||
m_gdbAdapter->shutdown();
|
||||
switch (state()) {
|
||||
case DebuggerNotReady: // Nothing to do! :)
|
||||
case EngineStarting: // We can't get here, really
|
||||
case InferiorShuttingDown: // Will auto-trigger further shutdown steps
|
||||
case EngineShuttingDown: // Do not disturb! :)
|
||||
break;
|
||||
case AdapterStarting: // GDB is up, adapter is "doing something"
|
||||
setState(AdapterStartFailed);
|
||||
m_gdbAdapter->shutdown();
|
||||
// fall-through
|
||||
case AdapterStartFailed: // Adapter "did something", but it did not help
|
||||
// FIXME set some timeout?
|
||||
postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit));
|
||||
break;
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunning:
|
||||
case InferiorStopping:
|
||||
case InferiorStopped:
|
||||
// FIXME set some timeout?
|
||||
postCommand(_(m_gdbAdapter->inferiorShutdownCommand()),
|
||||
NeedsStop, CB(handleInferiorShutdown));
|
||||
setState(InferiorShuttingDown); // Do it after posting the command!
|
||||
break;
|
||||
case AdapterStarted: // We can't get here, really
|
||||
case InferiorStartFailed:
|
||||
case InferiorShutDown:
|
||||
case InferiorShutdownFailed: // Whatever
|
||||
case InferiorUnrunnable:
|
||||
// FIXME set some timeout?
|
||||
postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit));
|
||||
setState(EngineShuttingDown); // Do it after posting the command!
|
||||
break;
|
||||
case InferiorStarting: // This may take some time, so just short-circuit it
|
||||
setState(InferiorStartFailed);
|
||||
// fall-through
|
||||
case InferiorStopFailed: // Tough luck, I guess. But unreachable as of now anyway.
|
||||
setState(EngineShuttingDown);
|
||||
m_gdbProc.terminate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::handleInferiorShutdown(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
|
||||
setState(InferiorShutDown);
|
||||
} else {
|
||||
debugMessage(_("INFERIOR SHUTDOWN FAILED"));
|
||||
setState(InferiorShutdownFailed);
|
||||
QString msg = m_gdbAdapter->msgInferiorStopFailed(_(response.data.findChild("msg").data()));
|
||||
showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
|
||||
}
|
||||
shutdown(); // re-iterate...
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultExit) {
|
||||
debugMessage(_("GDB CLAIMS EXIT; WAITING"));
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
QString msg = m_gdbAdapter->msgGdbStopFailed(_(response.data.findChild("msg").data()));
|
||||
debugMessage(_("GDB WON'T EXIT (%1); KILLING IT").arg(msg));
|
||||
m_gdbProc.terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::detachDebugger()
|
||||
@@ -1383,8 +1446,7 @@ void GdbEngine::detachDebugger()
|
||||
void GdbEngine::exitDebugger() // called from the manager
|
||||
{
|
||||
disconnectDebuggingHelperActions();
|
||||
initializeVariables();
|
||||
m_gdbAdapter->shutdown();
|
||||
shutdown();
|
||||
}
|
||||
|
||||
int GdbEngine::currentFrame() const
|
||||
@@ -1445,17 +1507,17 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
|
||||
// initializeVariables());
|
||||
//QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0);
|
||||
|
||||
initializeVariables();
|
||||
|
||||
m_startParameters = sp;
|
||||
|
||||
delete m_gdbAdapter;
|
||||
m_gdbAdapter = createAdapter(sp);
|
||||
connectAdapter();
|
||||
|
||||
if (startModeAllowsDumpers())
|
||||
connectDebuggingHelperActions();
|
||||
|
||||
initializeVariables();
|
||||
connectAdapter();
|
||||
|
||||
m_gdbAdapter->startAdapter();
|
||||
}
|
||||
|
||||
@@ -4089,19 +4151,37 @@ void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
|
||||
// Starting up & shutting down
|
||||
//
|
||||
|
||||
void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint)
|
||||
bool GdbEngine::startGdb(const QStringList &args, const QString &gdb)
|
||||
{
|
||||
setState(AdapterStartFailed);
|
||||
debugMessage(_("ADAPTER START FAILED"));
|
||||
Core::ICore::instance()->showWarningWithOptions(tr("Adapter start failed"), msg, QString(),
|
||||
QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
|
||||
shutdown();
|
||||
}
|
||||
debugMessage(_("STARTING GDB ") + gdb);
|
||||
|
||||
void GdbEngine::handleAdapterStarted()
|
||||
{
|
||||
setState(AdapterStarted);
|
||||
debugMessage(_("ADAPTER SUCCESSFULLY STARTED, INITIALIZING GDB"));
|
||||
m_gdbProc.disconnect(); // From any previous runs
|
||||
|
||||
QString location = gdb;
|
||||
if (location.isEmpty())
|
||||
location = theDebuggerStringSetting(GdbLocation);
|
||||
QStringList gdbArgs;
|
||||
gdbArgs << _("-i");
|
||||
gdbArgs << _("mi");
|
||||
gdbArgs += args;
|
||||
m_gdbProc.start(location, gdbArgs);
|
||||
|
||||
if (!m_gdbProc.waitForStarted()) {
|
||||
handleAdapterStartFailed(m_gdbProc.errorString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do this only after the process is running, so we get no needless error notifications
|
||||
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
SLOT(handleGdbError(QProcess::ProcessError)));
|
||||
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
|
||||
SLOT(readGdbStandardOutput()));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
|
||||
SLOT(readGdbStandardError()));
|
||||
|
||||
debugMessage(_("GDB STARTED, INITIALIZING IT"));
|
||||
|
||||
postCommand(_("show version"), CB(handleShowVersion));
|
||||
postCommand(_("help bb"), CB(handleIsSynchroneous));
|
||||
@@ -4185,12 +4265,69 @@ void GdbEngine::handleAdapterStarted()
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("HANDLE GDB ERROR"));
|
||||
switch (error) {
|
||||
case QProcess::Crashed:
|
||||
break; // will get a processExited() as well
|
||||
// impossible case QProcess::FailedToStart:
|
||||
case QProcess::ReadError:
|
||||
case QProcess::WriteError:
|
||||
case QProcess::Timedout:
|
||||
default:
|
||||
m_gdbProc.terminate();
|
||||
setState(EngineShuttingDown, true);
|
||||
showMessageBox(QMessageBox::Critical, tr("Gdb I/O Error"),
|
||||
errorMessage(error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbFinished(int code, QProcess::ExitStatus type)
|
||||
{
|
||||
debugMessage(_("GDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
|
||||
if (state() == EngineShuttingDown) {
|
||||
m_gdbAdapter->shutdown();
|
||||
} else if (state() != AdapterStartFailed) {
|
||||
showMessageBox(QMessageBox::Critical, tr("Unexpected Gdb Exit"),
|
||||
tr("The gdb process exited unexpectedly (%1).")
|
||||
.arg((type == QProcess::CrashExit)
|
||||
? tr("crashed") : tr("code %1").arg(code)));
|
||||
m_gdbAdapter->shutdown();
|
||||
}
|
||||
initializeVariables();
|
||||
setState(DebuggerNotReady, true);
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint)
|
||||
{
|
||||
setState(AdapterStartFailed);
|
||||
debugMessage(_("ADAPTER START FAILED"));
|
||||
Core::ICore::instance()->showWarningWithOptions(
|
||||
tr("Adapter start failed"), msg, QString(),
|
||||
_(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterStarted()
|
||||
{
|
||||
setState(AdapterStarted);
|
||||
debugMessage(_("ADAPTER SUCCESSFULLY STARTED"));
|
||||
|
||||
// Initial attempt to set breakpoints
|
||||
showStatusMessage(tr("Setting breakpoints..."));
|
||||
attemptBreakpointSynchronization();
|
||||
|
||||
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
|
||||
m_commandsDoneCallback = &GdbEngine::startInferior;
|
||||
if (m_cookieForToken.isEmpty()) {
|
||||
startInferior();
|
||||
} else {
|
||||
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
|
||||
m_commandsDoneCallback = &GdbEngine::startInferior;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::startInferior()
|
||||
@@ -4209,48 +4346,23 @@ void GdbEngine::handleInferiorStartFailed(const QString &msg)
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void GdbEngine::handleInferiorShutDown()
|
||||
{
|
||||
debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
|
||||
}
|
||||
|
||||
void GdbEngine::handleInferiorShutdownFailed(const QString &msg)
|
||||
{
|
||||
debugMessage(_("INFERIOR SHUTDOWN FAILED"));
|
||||
showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
|
||||
shutdown(); // continue with adapter shutdown
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterCrashed(const QString &msg)
|
||||
{
|
||||
debugMessage(_("ADAPTER CRASHED"));
|
||||
switch (state()) {
|
||||
// All fall-through.
|
||||
case InferiorRunning:
|
||||
setState(InferiorShuttingDown);
|
||||
case InferiorShuttingDown:
|
||||
setState(InferiorShutDown);
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
default:
|
||||
setState(DebuggerNotReady);
|
||||
}
|
||||
|
||||
// The adapter is expected to have cleaned up after itself when we get here,
|
||||
// so the effect is about the same as AdapterStartFailed => use it.
|
||||
// Don't bother with state transitions - this can happen in any state and
|
||||
// the end result is always the same, so it makes little sense to find a
|
||||
// "path" which does not assert.
|
||||
setState(AdapterStartFailed, true);
|
||||
|
||||
// No point in being friendly here ...
|
||||
m_gdbProc.terminate();
|
||||
|
||||
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterShutDown()
|
||||
{
|
||||
debugMessage(_("ADAPTER SUCCESSFULLY SHUT DOWN"));
|
||||
setState(DebuggerNotReady);
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterShutdownFailed(const QString &msg)
|
||||
{
|
||||
debugMessage(_("ADAPTER SHUTDOWN FAILED"));
|
||||
showMessageBox(QMessageBox::Critical, tr("Adapter shutdown failed"), msg);
|
||||
setState(DebuggerNotReady);
|
||||
}
|
||||
|
||||
void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const
|
||||
{
|
||||
opts->push_back(new GdbOptionsPage);
|
||||
|
@@ -125,14 +125,20 @@ private: ////////// Gdb Process Management //////////
|
||||
|
||||
AbstractGdbAdapter *createAdapter(const DebuggerStartParametersPtr &dp);
|
||||
void connectAdapter();
|
||||
bool startGdb(const QStringList &args = QStringList(), const QString &gdb = QString());
|
||||
void startInferior();
|
||||
|
||||
void handleInferiorShutdown(const GdbResponse &response);
|
||||
void handleGdbExit(const GdbResponse &response);
|
||||
|
||||
void gdbInputAvailable(int channel, const QString &msg)
|
||||
{ m_manager->showDebuggerInput(channel, msg); }
|
||||
void gdbOutputAvailable(int channel, const QString &msg)
|
||||
{ m_manager->showDebuggerOutput(channel, msg); }
|
||||
|
||||
private slots:
|
||||
void handleGdbFinished(int, QProcess::ExitStatus status);
|
||||
void handleGdbError(QProcess::ProcessError error);
|
||||
void readGdbStandardOutput();
|
||||
void readGdbStandardError();
|
||||
void readDebugeeOutput(const QByteArray &data);
|
||||
@@ -141,12 +147,8 @@ private slots:
|
||||
void handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint = QString());
|
||||
|
||||
void handleInferiorStartFailed(const QString &msg);
|
||||
void handleInferiorShutDown();
|
||||
void handleInferiorShutdownFailed(const QString &msg);
|
||||
|
||||
void handleAdapterCrashed(const QString &msg);
|
||||
void handleAdapterShutDown();
|
||||
void handleAdapterShutdownFailed(const QString &msg);
|
||||
|
||||
private:
|
||||
QTextCodec *m_outputCodec;
|
||||
@@ -154,6 +156,7 @@ private:
|
||||
|
||||
QByteArray m_inbuffer;
|
||||
|
||||
QProcess m_gdbProc;
|
||||
AbstractGdbAdapter *m_gdbAdapter;
|
||||
|
||||
private: ////////// Gdb Command Management //////////
|
||||
|
@@ -58,8 +58,6 @@ namespace Internal {
|
||||
PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
commonInit();
|
||||
|
||||
// Output
|
||||
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
|
||||
engine, SLOT(readDebugeeOutput(QByteArray)));
|
||||
@@ -72,36 +70,27 @@ void PlainGdbAdapter::startAdapter()
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.prepend(_("mi"));
|
||||
gdbArgs.prepend(_("-i"));
|
||||
|
||||
if (!m_outputCollector.listen()) {
|
||||
emit adapterStartFailed(tr("Cannot set up communication with child process: %1")
|
||||
.arg(m_outputCollector.errorString()), QString());
|
||||
return;
|
||||
}
|
||||
gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName());
|
||||
gdbArgs.append(_("--tty=") + m_outputCollector.serverName());
|
||||
|
||||
if (!startParameters().workingDir.isEmpty())
|
||||
m_gdbProc.setWorkingDirectory(startParameters().workingDir);
|
||||
m_engine->m_gdbProc.setWorkingDirectory(startParameters().workingDir);
|
||||
if (!startParameters().environment.isEmpty())
|
||||
m_gdbProc.setEnvironment(startParameters().environment);
|
||||
m_engine->m_gdbProc.setEnvironment(startParameters().environment);
|
||||
|
||||
m_gdbProc.start(theDebuggerStringSetting(GdbLocation), gdbArgs);
|
||||
}
|
||||
if (!m_engine->startGdb(gdbArgs)) {
|
||||
m_outputCollector.shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
|
||||
emit adapterCrashed(m_engine->errorMessage(error));
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::startInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
@@ -159,74 +148,6 @@ void PlainGdbAdapter::shutdown()
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
|
||||
m_outputCollector.shutdown();
|
||||
switch (state()) {
|
||||
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunning:
|
||||
case InferiorStopping:
|
||||
case InferiorStopped:
|
||||
setState(InferiorShuttingDown);
|
||||
m_engine->postCommand(_("kill"), CB(handleKill));
|
||||
return;
|
||||
|
||||
case InferiorShuttingDown:
|
||||
// FIXME: How can we end up here?
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
// Fall through.
|
||||
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
/*
|
||||
case InferiorShutdownFailed:
|
||||
m_gdbProc.terminate();
|
||||
// 20s can easily happen when loading webkit debug information
|
||||
m_gdbProc.waitForFinished(20000);
|
||||
setState(AdapterShuttingDown);
|
||||
debugMessage(_("FORCING TERMINATION: %1").arg(state()));
|
||||
if (state() != QProcess::NotRunning) {
|
||||
debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1")
|
||||
.arg(state()));
|
||||
m_gdbProc.kill();
|
||||
}
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
*/
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
}
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleKill(const GdbResponse &response)
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER HANDLE KILL " + response.toString()));
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
setState(InferiorShutDown);
|
||||
emit inferiorShutDown();
|
||||
shutdown(); // re-iterate...
|
||||
} else {
|
||||
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorShutdownFailed);
|
||||
emit inferiorShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
|
||||
{
|
||||
debugMessage(_("GDB PROCESS FINISHED"));
|
||||
emit adapterShutDown();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -59,17 +59,12 @@ public:
|
||||
void startInferior();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
const char *inferiorShutdownCommand() const { return "kill"; }
|
||||
|
||||
private:
|
||||
void handleFileExecAndSymbols(const GdbResponse &response);
|
||||
void handleKill(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
void handleExecRun(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus status);
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
Q_SLOT void handleGdbStarted();
|
||||
|
||||
OutputCollector m_outputCollector;
|
||||
};
|
||||
|
||||
|
@@ -54,8 +54,6 @@ namespace Internal {
|
||||
RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
commonInit();
|
||||
|
||||
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(uploadProcError(QProcess::ProcessError)));
|
||||
connect(&m_uploadProc, SIGNAL(readyReadStandardOutput()),
|
||||
@@ -70,12 +68,6 @@ void RemoteGdbAdapter::startAdapter()
|
||||
setState(AdapterStarting);
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.prepend(_("mi"));
|
||||
gdbArgs.prepend(_("-i"));
|
||||
|
||||
QString location = theDebuggerStringSetting(GdbLocation);
|
||||
|
||||
// FIXME: make asynchroneous
|
||||
// Start the remote server
|
||||
if (startParameters().serverStartScript.isEmpty()) {
|
||||
@@ -86,23 +78,13 @@ void RemoteGdbAdapter::startAdapter()
|
||||
m_uploadProc.waitForStarted();
|
||||
}
|
||||
|
||||
// Start the debugger
|
||||
m_gdbProc.start(location, gdbArgs);
|
||||
}
|
||||
if (!m_engine->startGdb())
|
||||
// FIXME: cleanup missing
|
||||
return;
|
||||
|
||||
void RemoteGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("ADAPTER, HANDLE GDB ERROR"));
|
||||
emit adapterCrashed(m_engine->errorMessage(error));
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::uploadProcError(QProcess::ProcessError error)
|
||||
{
|
||||
QString msg;
|
||||
@@ -232,55 +214,7 @@ void RemoteGdbAdapter::interruptInferior()
|
||||
|
||||
void RemoteGdbAdapter::shutdown()
|
||||
{
|
||||
switch (state()) {
|
||||
|
||||
case InferiorRunning:
|
||||
case InferiorStopped:
|
||||
setState(InferiorShuttingDown);
|
||||
m_engine->postCommand(_("kill"), CB(handleKill));
|
||||
return;
|
||||
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
// fall through
|
||||
|
||||
case InferiorStartFailed:
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::handleKill(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
setState(InferiorShutDown);
|
||||
emit inferiorShutDown();
|
||||
shutdown(); // re-iterate...
|
||||
} else {
|
||||
QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorShutdownFailed);
|
||||
emit inferiorShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
|
||||
{
|
||||
debugMessage(_("GDB PROESS FINISHED"));
|
||||
emit adapterShutDown();
|
||||
// FIXME: cleanup missing
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -69,12 +69,6 @@ private:
|
||||
#endif
|
||||
void handleFileExecAndSymbols(const GdbResponse &response);
|
||||
void handleTargetRemote(const GdbResponse &response);
|
||||
void handleKill(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleGdbStarted();
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
|
||||
|
||||
QProcess m_uploadProc;
|
||||
};
|
||||
|
@@ -204,10 +204,6 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
||||
#endif
|
||||
m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset);
|
||||
|
||||
commonInit();
|
||||
connect(&m_gdbProc, SIGNAL(stateChanged(QProcess::ProcessState)),
|
||||
this, SLOT(handleGdbStateChanged(QProcess::ProcessState)));
|
||||
|
||||
connect(&m_rfcommProc, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(handleRfcommReadyReadStandardError()));
|
||||
connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()),
|
||||
@@ -380,17 +376,6 @@ QByteArray TrkGdbAdapter::trkInterruptMessage()
|
||||
return ba;
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::emitDelayedAdapterStartFailed(const QString &msg)
|
||||
{
|
||||
m_adapterFailMessage = msg;
|
||||
QTimer::singleShot(0, this, SLOT(slotEmitDelayedAdapterStartFailed()));
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::slotEmitDelayedAdapterStartFailed()
|
||||
{
|
||||
emit adapterStartFailed(m_adapterFailMessage, TrkOptionsPage::settingsId());
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::emitDelayedInferiorStartFailed(const QString &msg)
|
||||
{
|
||||
m_adapterFailMessage = msg;
|
||||
@@ -437,7 +422,7 @@ void TrkGdbAdapter::waitForTrkConnect()
|
||||
// "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File
|
||||
//sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File
|
||||
|
||||
maybeAdapterStarted();
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::logMessage(const QString &msg)
|
||||
@@ -1527,50 +1512,6 @@ void TrkGdbAdapter::interruptInferior()
|
||||
sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
if (error == QProcess::FailedToStart) {
|
||||
const QString msg = QString::fromLatin1("GDB: Cannot start '%1': %2. Please check the settings.").arg(m_options->gdb).arg(m_gdbProc.errorString());
|
||||
emitDelayedAdapterStartFailed(msg); // Emitted from QProcess::start() on Windows
|
||||
} else {
|
||||
// Others should trigger handleGdbFinished
|
||||
const QString msg = QString::fromLatin1("GDB: Process error %1: %2").arg(error).arg(m_gdbProc.errorString());
|
||||
logMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
const QString msg = exitStatus == QProcess::NormalExit ?
|
||||
QString::fromLatin1("GDB: Process finished (exit code: %1).").arg(exitCode) :
|
||||
QString::fromLatin1("GDB: Process crashed: %1").arg(m_gdbProc.errorString());
|
||||
if (state() == AdapterStarting) {
|
||||
emitDelayedAdapterStartFailed(msg);// Potentially emitted from QProcess::start() on Windows
|
||||
} else {
|
||||
logMessage(msg);
|
||||
emit adapterShutDown();
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
logMessage(QString("GDB: Process Started"));
|
||||
maybeAdapterStarted();
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::maybeAdapterStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
if (m_gdbProc.state() == QProcess::Running && m_trkDevice.isOpen()) {
|
||||
emit adapterStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbStateChanged(QProcess::ProcessState newState)
|
||||
{
|
||||
logMessage(_("GDB: Process State %1").arg(newState));
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::startAdapter()
|
||||
{
|
||||
// Retrieve parameters
|
||||
@@ -1632,13 +1573,12 @@ void TrkGdbAdapter::startAdapter()
|
||||
connect(m_gdbServer, SIGNAL(newConnection()),
|
||||
this, SLOT(handleGdbConnection()));
|
||||
|
||||
logMessage("STARTING GDB");
|
||||
logMessage(_("### Starting gdb %1").arg(m_options->gdb));
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
|
||||
gdbArgs.append(QLatin1String("-i"));
|
||||
gdbArgs.append(QLatin1String("mi"));
|
||||
m_gdbProc.start(m_options->gdb, gdbArgs);
|
||||
if (!m_engine->startGdb(gdbArgs, m_options->gdb)) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
waitForTrkConnect();
|
||||
}
|
||||
@@ -1792,7 +1732,7 @@ void TrkGdbAdapter::write(const QByteArray &data)
|
||||
trkReadMemoryMessage(m_session.dataseg, 12));
|
||||
return;
|
||||
}
|
||||
m_gdbProc.write(data);
|
||||
m_engine->m_gdbProc.write(data);
|
||||
}
|
||||
|
||||
uint oldPC;
|
||||
@@ -1990,79 +1930,7 @@ void TrkGdbAdapter::cleanup()
|
||||
|
||||
void TrkGdbAdapter::shutdown()
|
||||
{
|
||||
switch (state()) {
|
||||
case AdapterStarting:
|
||||
case AdapterStartFailed:
|
||||
cleanup();
|
||||
setState(DebuggerNotReady);
|
||||
return;
|
||||
|
||||
case InferiorStopping:
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunning:
|
||||
//sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
|
||||
// Fall through.
|
||||
|
||||
case InferiorStopped:
|
||||
//sendTrkMessage(0x41, TrkCallback(), trkDeleteProcessMessage(), "Delete process");
|
||||
//sendTrkMessage(0x02, TrkCB(handleDisconnect));
|
||||
setState(InferiorShuttingDown);
|
||||
m_engine->postCommand(_("kill"), CB(handleKill));
|
||||
return;
|
||||
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
cleanup();
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
/*
|
||||
if (m_options->mode == TrkOptions::BlueTooth
|
||||
&& m_rfcommProc.state() == QProcess::Running)
|
||||
m_rfcommProc.kill();
|
||||
m_rfcommProc.terminate();
|
||||
m_rfcommProc.write(ba);
|
||||
m_rfcommProc.terminate();
|
||||
m_rfcommProc.waitForFinished();
|
||||
|
||||
m_gdbProc.kill();
|
||||
m_gdbProc.terminate();
|
||||
|
||||
QByteArray ba;
|
||||
ba.append(0x03);
|
||||
QProcess proc;
|
||||
proc.start("rfcomm release " + m_options->blueToothDevice);
|
||||
proc.waitForFinished();
|
||||
m_gdbProc.waitForFinished(msecs);
|
||||
*/
|
||||
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleKill(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
setState(InferiorShutDown);
|
||||
emit inferiorShutDown();
|
||||
shutdown(); // re-iterate...
|
||||
} else {
|
||||
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorShutdownFailed);
|
||||
emit inferiorShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
qDebug() << "EXITED, NO MESSAGE...";
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -163,8 +163,6 @@ public:
|
||||
//
|
||||
void start(const QString &program, const QStringList &args,
|
||||
QIODevice::OpenMode mode = QIODevice::ReadWrite);
|
||||
QByteArray readAllStandardError();
|
||||
QByteArray readAllStandardOutput();
|
||||
void write(const QByteArray &data);
|
||||
bool isTrkAdapter() const { return true; }
|
||||
bool dumpersAvailable() const { return false; }
|
||||
@@ -174,15 +172,12 @@ private:
|
||||
void startInferior();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
|
||||
void cleanup();
|
||||
void emitDelayedAdapterStartFailed(const QString &msg);
|
||||
Q_SLOT void slotEmitDelayedAdapterStartFailed();
|
||||
void emitDelayedInferiorStartFailed(const QString &msg);
|
||||
Q_SLOT void slotEmitDelayedInferiorStartFailed();
|
||||
|
||||
Q_SLOT void waitForTrkConnect();
|
||||
void handleKill(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
void handleTargetRemote(const GdbResponse &response);
|
||||
void handleFirstContinue(const GdbResponse &response);
|
||||
|
||||
@@ -285,13 +280,6 @@ private:
|
||||
bool sendGdbServerPacket(const QByteArray &packet, bool doFlush);
|
||||
void tryAnswerGdbMemoryRequest(bool buffered);
|
||||
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
Q_SLOT void handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
Q_SLOT void handleGdbStarted();
|
||||
Q_SLOT void handleGdbStateChanged(QProcess::ProcessState newState);
|
||||
|
||||
void maybeAdapterStarted();
|
||||
|
||||
void logMessage(const QString &msg); // triggers output() if m_verbose
|
||||
Q_SLOT void trkLogMessage(const QString &msg);
|
||||
|
||||
|
@@ -123,7 +123,7 @@ public:
|
||||
protected:
|
||||
void showStatusMessage(const QString &msg, int timeout = -1);
|
||||
DebuggerState state() const;
|
||||
void setState(DebuggerState state);
|
||||
void setState(DebuggerState state, bool forced = false);
|
||||
DebuggerManager *manager() const { return m_manager; }
|
||||
DebuggerManager *m_manager;
|
||||
|
||||
|
Reference in New Issue
Block a user