Debugger: Improve adapter error handling

Correctly reset state on missing Symbian gdb.
Provide "settings" options.
Reviewed-by: hjk <qtc-committer@nokia.com>
This commit is contained in:
Friedemann Kleint
2009-10-08 11:43:26 +02:00
parent 09e72eaa81
commit 81a8f2f927
10 changed files with 71 additions and 30 deletions

View File

@@ -28,6 +28,7 @@
**************************************************************************/ **************************************************************************/
#include "debuggerdialogs.h" #include "debuggerdialogs.h"
#include "debuggerconstants.h"
#include "ui_attachcoredialog.h" #include "ui_attachcoredialog.h"
#include "ui_attachexternaldialog.h" #include "ui_attachexternaldialog.h"
@@ -39,6 +40,8 @@
# include "shared/dbgwinutils.h" # include "shared/dbgwinutils.h"
#endif #endif
#include <coreplugin/icore.h>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QFile> #include <QtCore/QFile>
@@ -49,7 +52,7 @@
#include <QtGui/QPushButton> #include <QtGui/QPushButton>
#include <QtGui/QProxyModel> #include <QtGui/QProxyModel>
#include <QtGui/QSortFilterProxyModel> #include <QtGui/QSortFilterProxyModel>
#include <QtGui/QMessageBox>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -606,5 +609,28 @@ bool AddressDialog::isValid() const
return ok; return ok;
} }
int warningWithSettings(const QString &title,
const QString &text,
const QString &details,
const QString &settingsId,
QWidget *parent)
{
QMessageBox msgBox(QMessageBox::Warning, title, text,
QMessageBox::Ok, parent);
if (details.isEmpty())
msgBox.setDetailedText(details);
QAbstractButton *settingsButton = 0;
if (!settingsId.isEmpty())
settingsButton = msgBox.addButton(QCoreApplication::translate("Debugger::MessageBox", "Settings..."),
QMessageBox::AcceptRole);
const int dialogCode = msgBox.exec();
if (settingsButton && msgBox.clickedButton() == settingsButton) {
Core::ICore::instance()->showOptionsDialog(QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY),
settingsId);
return 2;
}
return dialogCode;
}
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -63,6 +63,14 @@ struct ProcData
QString state; QString state;
}; };
// Display a warning with an additional button to open
// the debugger settings dialog if settingsId is nonempty.
int warningWithSettings(const QString &title,
const QString &text,
const QString &details = QString(),
const QString &settingsId = QString(),
QWidget *parent = 0);
class AttachCoreDialog : public QDialog class AttachCoreDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT

View File

@@ -1001,17 +1001,9 @@ void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
if (!d->m_engine) { if (!d->m_engine) {
emit debuggingFinished(); emit debuggingFinished();
// Create Message box with possibility to go to settings // Create Message box with possibility to go to settings
QAbstractButton *settingsButton = 0; const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3").
QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), arg(d->m_startParameters->executable, toolChainName, errorMessage);
tr("Cannot debug '%1' (tool chain: '%2'): %3"). warningWithSettings(tr("Warning"), msg, QString(), settingsIdHint);
arg(d->m_startParameters->executable, toolChainName, errorMessage),
QMessageBox::Ok);
if (!settingsIdHint.isEmpty())
settingsButton = msgBox.addButton(tr("Settings..."), QMessageBox::AcceptRole);
msgBox.exec();
if (msgBox.clickedButton() == settingsButton)
Core::ICore::instance()->showOptionsDialog(
_(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
return; return;
} }

View File

@@ -69,7 +69,7 @@ public:
signals: signals:
void adapterStarted(); void adapterStarted();
void adapterStartFailed(const QString &msg); void adapterStartFailed(const QString &msg, const QString &settingsIdHint);
void adapterShutDown(); void adapterShutDown();
void adapterShutdownFailed(const QString &msg); void adapterShutdownFailed(const QString &msg);
void adapterCrashed(const QString &msg); void adapterCrashed(const QString &msg);

View File

@@ -80,7 +80,7 @@ void AttachGdbAdapter::startAdapter()
if (!m_engine->m_outputCollector.listen()) { if (!m_engine->m_outputCollector.listen()) {
emit adapterStartFailed(tr("Cannot set up communication with child process: %1") emit adapterStartFailed(tr("Cannot set up communication with child process: %1")
.arg(m_engine->m_outputCollector.errorString())); .arg(m_engine->m_outputCollector.errorString()), QString());
return; return;
} }
gdbArgs.prepend(_("--tty=") + m_engine->m_outputCollector.serverName()); gdbArgs.prepend(_("--tty=") + m_engine->m_outputCollector.serverName());

View File

@@ -80,7 +80,7 @@ void CoreGdbAdapter::startAdapter()
if (!m_engine->m_outputCollector.listen()) { if (!m_engine->m_outputCollector.listen()) {
emit adapterStartFailed(tr("Cannot set up communication with child process: %1") emit adapterStartFailed(tr("Cannot set up communication with child process: %1")
.arg(m_engine->m_outputCollector.errorString())); .arg(m_engine->m_outputCollector.errorString()), QString());
return; return;
} }
gdbArgs.prepend(_("--tty=") + m_engine->m_outputCollector.serverName()); gdbArgs.prepend(_("--tty=") + m_engine->m_outputCollector.serverName());

View File

@@ -261,8 +261,8 @@ void GdbEngine::connectAdapter()
connect(m_gdbAdapter, SIGNAL(adapterStarted()), connect(m_gdbAdapter, SIGNAL(adapterStarted()),
this, SLOT(handleAdapterStarted())); this, SLOT(handleAdapterStarted()));
connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString)), connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)),
this, SLOT(handleAdapterStartFailed(QString))); this, SLOT(handleAdapterStartFailed(QString,QString)));
connect(m_gdbAdapter, SIGNAL(adapterShutDown()), connect(m_gdbAdapter, SIGNAL(adapterShutDown()),
this, SLOT(handleAdapterShutDown())); this, SLOT(handleAdapterShutDown()));
connect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)), connect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)),
@@ -4051,10 +4051,11 @@ void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
// Starting up & shutting down // Starting up & shutting down
// //
void GdbEngine::handleAdapterStartFailed(const QString &msg) void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint)
{ {
setState(AdapterStartFailed);
debugMessage(_("ADAPTER START FAILED")); debugMessage(_("ADAPTER START FAILED"));
showMessageBox(QMessageBox::Critical, tr("Adapter start failed"), msg); warningWithSettings(tr("Adapter start failed"), msg, QString(), settingsIdHint);
shutdown(); shutdown();
} }

View File

@@ -238,7 +238,7 @@ private slots:
void readDebugeeOutput(const QByteArray &data); void readDebugeeOutput(const QByteArray &data);
void handleAdapterStarted(); void handleAdapterStarted();
void handleAdapterStartFailed(const QString &msg); void handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint = QString());
void handleInferiorPrepared(); void handleInferiorPrepared();
void handleInferiorPreparationFailed(const QString &msg); void handleInferiorPreparationFailed(const QString &msg);

View File

@@ -345,7 +345,7 @@ void PlainGdbAdapter::emitAdapterStartFailed(const QString &msg)
bool blocked = m_stubProc.blockSignals(true); bool blocked = m_stubProc.blockSignals(true);
m_stubProc.stop(); m_stubProc.stop();
m_stubProc.blockSignals(blocked); m_stubProc.blockSignals(blocked);
emit adapterStartFailed(msg); emit adapterStartFailed(msg, QString());
} }
} // namespace Internal } // namespace Internal

View File

@@ -29,6 +29,7 @@
#include "trkgdbadapter.h" #include "trkgdbadapter.h"
#include "trkoptions.h" #include "trkoptions.h"
#include "trkoptionspage.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
#ifndef STANDALONE_RUNNER #ifndef STANDALONE_RUNNER
#include "gdbengine.h" #include "gdbengine.h"
@@ -397,7 +398,7 @@ void TrkGdbAdapter::emitDelayedAdapterStartFailed(const QString &msg)
void TrkGdbAdapter::slotEmitDelayedAdapterStartFailed() void TrkGdbAdapter::slotEmitDelayedAdapterStartFailed()
{ {
emit adapterStartFailed(m_adapterFailMessage); emit adapterStartFailed(m_adapterFailMessage, TrkOptionsPage::settingsId());
} }
void TrkGdbAdapter::startInferiorEarly() void TrkGdbAdapter::startInferiorEarly()
@@ -420,7 +421,7 @@ void TrkGdbAdapter::startInferiorEarly()
QString msg = _("Failed to connect to %1 after " QString msg = _("Failed to connect to %1 after "
"%2 attempts").arg(device).arg(m_waitCount); "%2 attempts").arg(device).arg(m_waitCount);
logMessage(msg); logMessage(msg);
emit adapterStartFailed(msg); emit adapterStartFailed(msg, TrkOptionsPage::settingsId());
} }
return; return;
} }
@@ -1585,16 +1586,28 @@ void TrkGdbAdapter::interruptInferior()
void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error) void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error)
{ {
logMessage(QString("GDB: Process Error %1: %2") if (error == QProcess::FailedToStart) {
.arg(error).arg(m_gdbProc.errorString())); 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) void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus)
{ {
logMessage(QString("GDB: ProcessFinished %1 %2") const QString msg = exitStatus == QProcess::NormalExit ?
.arg(exitCode).arg(exitStatus)); QString::fromLatin1("GDB: Process finished (exit code: %1).").arg(exitCode) :
setState(DebuggerNotReady); QString::fromLatin1("GDB: Process crashed: %1").arg(m_gdbProc.errorString());
emit adapterShutDown(); if (state() == AdapterStarting) {
emitDelayedAdapterStartFailed(msg);// Potentially emitted from QProcess::start() on Windows
} else {
logMessage(msg);
setState(DebuggerNotReady);
emit adapterShutDown();
}
} }
void TrkGdbAdapter::handleGdbStarted() void TrkGdbAdapter::handleGdbStarted()
@@ -1647,7 +1660,7 @@ void TrkGdbAdapter::startAdapter()
"listener %1 on %2: %3\n"); "listener %1 on %2: %3\n");
msg = msg.arg(blueToothListener, device, m_rfcommProc.errorString()); msg = msg.arg(blueToothListener, device, m_rfcommProc.errorString());
msg += QString::fromLocal8Bit(m_rfcommProc.readAllStandardError()); msg += QString::fromLocal8Bit(m_rfcommProc.readAllStandardError());
emit adapterStartFailed(msg); emit adapterStartFailed(msg, TrkOptionsPage::settingsId());
return; return;
} }
} }
@@ -2070,6 +2083,7 @@ void TrkGdbAdapter::shutdown()
{ {
switch (state()) { switch (state()) {
case AdapterStarting: case AdapterStarting:
case AdapterStartFailed:
cleanup(); cleanup();
setState(DebuggerNotReady); setState(DebuggerNotReady);
return; return;