Commit 00f67670 authored by hjk's avatar hjk
Browse files

debugger: work on handling gdb crashes gracefully

parent 978cf4bd
......@@ -928,16 +928,6 @@ void DebuggerManager::exitDebugger()
m_engine->exitDebugger();
cleanupViews();
setState(DebuggerNotReady);
setBusyCursor(false);
emit debuggingFinished();
}
void DebuggerManager::notifyEngineFinished()
{
cleanupViews();
setState(DebuggerNotReady);
setBusyCursor(false);
emit debuggingFinished();
}
DebuggerStartParametersPtr DebuggerManager::startParameters() const
......@@ -1529,6 +1519,11 @@ void DebuggerManager::setState(DebuggerState state)
if (m_state == InferiorStopped)
resetLocation();
if (m_state == DebuggerNotReady) {
setBusyCursor(false);
emit debuggingFinished();
}
const bool started = state == InferiorRunning
|| state == InferiorRunningRequested
|| state == InferiorStopping
......
......@@ -256,7 +256,6 @@ private:
void notifyInferiorRunning();
void notifyInferiorExited();
void notifyInferiorPidChanged(qint64);
void notifyEngineFinished();
void cleanupViews();
......
......@@ -72,7 +72,7 @@ signals:
void adapterStartFailed(const QString &msg);
void adapterShutDown();
void adapterShutdownFailed(const QString &msg);
void adapterCrashed();
void adapterCrashed(const QString &msg);
void inferiorPrepared();
void inferiorPreparationFailed(const QString &msg);
......@@ -83,7 +83,6 @@ signals:
void inferiorPidChanged(qint64 pid);
void error(QProcess::ProcessError);
void readyReadStandardOutput();
void readyReadStandardError();
......
......@@ -56,7 +56,7 @@ AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent)
{
QTC_ASSERT(state() == DebuggerNotReady, qDebug() << state());
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
this, SIGNAL(error(QProcess::ProcessError)));
this, SLOT(handleGdbError(QProcess::ProcessError)));
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
this, SIGNAL(readyReadStandardOutput()));
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
......@@ -100,6 +100,13 @@ void AttachGdbAdapter::handleGdbStarted()
emit adapterStarted();
}
void AttachGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
emit adapterCrashed(m_engine->errorMessage(error));
shutdown();
}
void AttachGdbAdapter::prepareInferior()
{
QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
......
......@@ -72,8 +72,9 @@ private:
void handleDetach(const GdbResponse &response);
void handleExit(const GdbResponse &response);
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
Q_SLOT void handleGdbStarted();
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
Q_SLOT void handleGdbError(QProcess::ProcessError error);
QProcess m_gdbProc;
};
......
......@@ -56,7 +56,7 @@ CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
{
QTC_ASSERT(state() == DebuggerNotReady, qDebug() << state());
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
this, SIGNAL(error(QProcess::ProcessError)));
this, SLOT(handleGdbError(QProcess::ProcessError)));
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
this, SIGNAL(readyReadStandardOutput()));
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
......@@ -100,6 +100,13 @@ void CoreGdbAdapter::handleGdbStarted()
emit adapterStarted();
}
void CoreGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
emit adapterCrashed(m_engine->errorMessage(error));
shutdown();
}
void CoreGdbAdapter::prepareInferior()
{
QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
......
......@@ -71,8 +71,9 @@ private:
void handleTargetCore(const GdbResponse &response);
void handleExit(const GdbResponse &response);
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
Q_SLOT void handleGdbStarted();
Q_SLOT void handleGdbError(QProcess::ProcessError error);
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
QProcess m_gdbProc;
};
......
......@@ -242,8 +242,6 @@ GdbEngine::~GdbEngine()
void GdbEngine::connectAdapter()
{
// Gdb Process interaction
connect(m_gdbAdapter, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(gdbProcError(QProcess::ProcessError)));
connect(m_gdbAdapter, SIGNAL(readyReadStandardOutput()),
this, SLOT(readGdbStandardOutput()));
connect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
......@@ -272,8 +270,8 @@ void GdbEngine::connectAdapter()
connect(m_gdbAdapter, SIGNAL(inferiorShutdownFailed(QString)),
this, SLOT(handleInferiorShutdownFailed(QString)));
connect(m_gdbAdapter, SIGNAL(adapterCrashed()),
this, SLOT(handleAdapterCrashed()));
connect(m_gdbAdapter, SIGNAL(adapterCrashed(QString)),
this, SLOT(handleAdapterCrashed(QString)));
}
void GdbEngine::disconnectAdapter()
......@@ -315,47 +313,31 @@ void GdbEngine::initializeVariables()
//m_gdbAdapter;
}
void GdbEngine::gdbProcError(QProcess::ProcessError error)
QString GdbEngine::errorMessage(QProcess::ProcessError error)
{
QString msg;
bool kill = true;
switch (error) {
case QProcess::FailedToStart:
//kill = false;
msg = tr("The Gdb process failed to start. Either the "
return tr("The Gdb process failed to start. Either the "
"invoked program '%1' is missing, or you may have insufficient "
"permissions to invoke the program.")
.arg(theDebuggerStringSetting(GdbLocation));
//emit startFailed();
//shutdown();
break;
case QProcess::Crashed:
kill = false;
msg = tr("The Gdb process crashed some time after starting "
return tr("The Gdb process crashed some time after starting "
"successfully.");
break;
case QProcess::Timedout:
msg = tr("The last waitFor...() function timed out. "
return tr("The last waitFor...() function timed out. "
"The state of QProcess is unchanged, and you can try calling "
"waitFor...() again.");
break;
case QProcess::WriteError:
msg = tr("An error occurred when attempting to write "
return tr("An error occurred when attempting to write "
"to the Gdb process. For example, the process may not be running, "
"or it may have closed its input channel.");
break;
case QProcess::ReadError:
msg = tr("An error occurred when attempting to read from "
return tr("An error occurred when attempting to read from "
"the Gdb process. For example, the process may not be running.");
break;
default:
msg = tr("An unknown error in the Gdb process occurred. "
"This is the default return value of error().");
return tr("An unknown error in the Gdb process occurred. ");
}
showStatusMessage(msg);
showMessageBox(QMessageBox::Critical, tr("Error"), msg);
shutdown();
}
#if 0
......@@ -1007,6 +989,7 @@ void GdbEngine::handleExecRunToFunction(const GdbResponse &response)
// 14*stopped,thread-id="1",frame={addr="0x0000000000403ce4",
// func="foo",args=[{name="str",value="@0x7fff0f450460"}],
// file="main.cpp",fullname="/tmp/g/main.cpp",line="37"}
QTC_ASSERT(state() == InferiorStopping, qDebug() << state())
setState(InferiorStopped);
showStatusMessage(tr("Function reached. Stopped."));
GdbMi frame = response.data.findChild("frame");
......@@ -1040,6 +1023,7 @@ static bool isStoppedReason(const QByteArray &reason)
;
}
#if 0
void GdbEngine::handleAqcuiredInferior()
{
#ifdef Q_OS_WIN
......@@ -1082,6 +1066,7 @@ void GdbEngine::handleAqcuiredInferior()
reloadModules();
attemptBreakpointSynchronization();
}
#endif
void GdbEngine::handleAsyncOutput(const GdbMi &data)
{
......@@ -1144,11 +1129,11 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
// signal-meaning="Trace/breakpoint trap",thread-id="2",
// frame={addr="0x7c91120f",func="ntdll!DbgUiConnectToDbg",
// args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
if (reason == "signal-received"
&& data.findChild("signal-name").toString() == "SIGTRAP") {
continueInferior();
return;
}
//if (reason == "signal-received"
// && data.findChild("signal-name").data() == "SIGTRAP") {
// continueInferior();
// return;
//}
// jump over well-known frames
static int stepCounter = 0;
......@@ -1181,8 +1166,16 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
}
if (isStoppedReason(reason) || reason.isEmpty()) {
QVariant var = QVariant::fromValue<GdbMi>(data);
if (m_debuggingHelperState == DebuggingHelperUninitialized) {
QVariant var = QVariant::fromValue<GdbMi>(data);
// Don't load helpers on stops triggered by signals unless it's
// an intentional trap.
bool initHelpers = m_debuggingHelperState == DebuggingHelperUninitialized;
if (reason == "signal-received"
&& data.findChild("signal-name").data() != "SIGTRAP")
initHelpers = false;
if (initHelpers) {
tryLoadDebuggingHelpers();
postCommand(_("p 4"), CB(handleStop1), var); // dummy
} else {
......@@ -4159,24 +4152,34 @@ void GdbEngine::handleInferiorShutdownFailed(const QString &msg)
shutdown(); // continue with adapter shutdown
}
void GdbEngine::handleAdapterCrashed()
void GdbEngine::handleAdapterCrashed(const QString &msg)
{
debugMessage(_("ADAPTER CRASHED"));
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), QString());
shutdown();
switch (state()) {
// All fall-through.
case InferiorRunning:
setState(InferiorShuttingDown);
case InferiorShuttingDown:
setState(InferiorShutDown);
case InferiorShutDown:
setState(AdapterShuttingDown);
default:
setState(DebuggerNotReady);
}
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
}
void GdbEngine::handleAdapterShutDown()
{
debugMessage(_("ADAPTER SUCCESSFULLY SHUT DOWN"));
manager()->notifyEngineFinished();
setState(DebuggerNotReady);
}
void GdbEngine::handleAdapterShutdownFailed(const QString &msg)
{
debugMessage(_("ADAPTER SHUTDOWN FAILED"));
showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
manager()->notifyEngineFinished();
setState(DebuggerNotReady);
}
void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const
......
......@@ -229,7 +229,7 @@ private:
void updateLocals();
private slots:
void gdbProcError(QProcess::ProcessError error);
QString errorMessage(QProcess::ProcessError error);
void readGdbStandardOutput();
void readGdbStandardError();
void readDebugeeOutput(const QByteArray &data);
......@@ -244,7 +244,7 @@ private slots:
void handleInferiorShutDown();
void handleInferiorShutdownFailed(const QString &msg);
void handleAdapterCrashed();
void handleAdapterCrashed(const QString &msg);
void handleAdapterShutDown();
void handleAdapterShutdownFailed(const QString &msg);
......@@ -252,7 +252,6 @@ private:
int terminationIndex(const QByteArray &buffer, int &length);
void handleResponse(const QByteArray &buff);
void handleStart(const GdbResponse &response);
void handleAqcuiredInferior();
void handleAsyncOutput(const GdbMi &data);
void handleStop1(const GdbResponse &response);
void handleStop2(const GdbResponse &response);
......
......@@ -59,7 +59,7 @@ PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent)
{
QTC_ASSERT(state() == DebuggerNotReady, qDebug() << state());
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
this, SIGNAL(error(QProcess::ProcessError)));
this, SLOT(handleGdbError(QProcess::ProcessError)));
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
this, SIGNAL(readyReadStandardOutput()));
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
......@@ -118,9 +118,7 @@ void PlainGdbAdapter::startAdapter()
setEnvironment(startParameters().environment);
}
QString location = theDebuggerStringSetting(GdbLocation);
//showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
m_gdbProc.start(location, gdbArgs);
m_gdbProc.start(theDebuggerStringSetting(GdbLocation), gdbArgs);
}
void PlainGdbAdapter::handleGdbStarted()
......@@ -130,6 +128,12 @@ void PlainGdbAdapter::handleGdbStarted()
emit adapterStarted();
}
void PlainGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
emit adapterCrashed(m_engine->errorMessage(error));
}
void PlainGdbAdapter::prepareInferior()
{
QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
......@@ -238,6 +242,7 @@ void PlainGdbAdapter::interruptInferior()
void PlainGdbAdapter::shutdown()
{
debugMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
switch (state()) {
case InferiorRunningRequested:
......@@ -275,6 +280,7 @@ void PlainGdbAdapter::shutdown()
void PlainGdbAdapter::handleKill(const GdbResponse &response)
{
debugMessage(_("PLAIN ADAPTER HANDLE KILL " + response.toString()));
if (response.resultClass == GdbResultDone) {
setState(InferiorShutDown);
emit inferiorShutDown();
......@@ -300,8 +306,7 @@ void PlainGdbAdapter::handleExit(const GdbResponse &response)
void PlainGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
{
debugMessage(_("GDB PROESS FINISHED"));
setState(DebuggerNotReady);
debugMessage(_("GDB PROCESS FINISHED"));
emit adapterShutDown();
}
......
......@@ -77,7 +77,8 @@ private:
void handleInfoTarget(const GdbResponse &response);
void emitAdapterStartFailed(const QString &msg);
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus status);
Q_SLOT void handleGdbError(QProcess::ProcessError error);
Q_SLOT void handleGdbStarted();
Q_SLOT void stubStarted();
Q_SLOT void stubError(const QString &msg);
......
......@@ -57,7 +57,7 @@ RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent)
{
QTC_ASSERT(state() == DebuggerNotReady, qDebug() << state());
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
this, SIGNAL(error(QProcess::ProcessError)));
this, SLOT(handleGdbError(QProcess::ProcessError)));
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
this, SIGNAL(readyReadStandardOutput()));
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
......@@ -124,6 +124,13 @@ void RemoteGdbAdapter::handleGdbStarted()
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;
......
......@@ -77,8 +77,9 @@ private:
void handleTargetRemote(const GdbResponse &response);
void handleFirstContinue(const GdbResponse &response);
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
Q_SLOT void handleGdbStarted();
Q_SLOT void handleGdbError(QProcess::ProcessError error);
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
QProcess m_gdbProc;
QProcess m_uploadProc;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment