debugger: gracefully handle commands that might not produce output

(cherry picked from commit 1324a1c600)

Conflicts:

	src/plugins/debugger/gdb/gdbengine.cpp
	src/plugins/debugger/gdb/gdbengine.h
This commit is contained in:
con
2010-01-06 15:52:14 +01:00
parent 0de840cb43
commit db68ca5b8d
4 changed files with 59 additions and 21 deletions

View File

@@ -1541,13 +1541,14 @@ void DebuggerManager::setSessionValue(const QString &name, const QVariant &value
emit setSessionValueRequested(name, value); emit setSessionValueRequested(name, value);
} }
void DebuggerManager::showMessageBox(int icon, QMessageBox *DebuggerManager::showMessageBox(int icon, const QString &title,
const QString &title, const QString &text) const QString &text, int buttons)
{ {
QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon), QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon),
title, text, QMessageBox::NoButton, mainWindow()); title, text, QMessageBox::StandardButtons(buttons), mainWindow());
mb->setAttribute(Qt::WA_DeleteOnClose); mb->setAttribute(Qt::WA_DeleteOnClose);
mb->show(); mb->show();
return mb;
} }
DebuggerState DebuggerManager::state() const DebuggerState DebuggerManager::state() const

View File

@@ -39,11 +39,12 @@
#include <QtCore/QVariant> #include <QtCore/QVariant>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAbstractItemModel;
class QAction; class QAction;
class QDebug;
class QDockWidget; class QDockWidget;
class QLabel; class QLabel;
class QDebug; class QMessageBox;
class QAbstractItemModel;
class QPoint; class QPoint;
class QVariant; class QVariant;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -177,7 +178,8 @@ public:
DebuggerStartParametersPtr startParameters() const; DebuggerStartParametersPtr startParameters() const;
qint64 inferiorPid() const; qint64 inferiorPid() const;
void showMessageBox(int icon, const QString &title, const QString &text); QMessageBox *showMessageBox(int icon, const QString &title, const QString &text,
int buttons = 0);
bool debuggerActionsEnabled() const; bool debuggerActionsEnabled() const;

View File

@@ -617,7 +617,7 @@ void GdbEngine::readGdbStandardError()
void GdbEngine::readGdbStandardOutput() void GdbEngine::readGdbStandardOutput()
{ {
if (m_commandTimer->isActive()) if (m_commandTimer->isActive())
m_commandTimer->start(); // Retrigger m_commandTimer->start(); // Retrigger
int newstart = 0; int newstart = 0;
@@ -816,19 +816,48 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0)
setState(InferiorShuttingDown); setState(InferiorShuttingDown);
} }
int GdbEngine::commandTimeoutTime() const
{
int time = theDebuggerAction(GdbWatchdogTimeout)->value().toInt();
return 1000 * qMax(20, time);
}
void GdbEngine::commandTimeout() void GdbEngine::commandTimeout()
{ {
// FIXME this needs a proper message box qDebug("TIMEOUT");
debugMessage(_("TIMED OUT WAITING FOR GDB REPLY. COMMANDS STILL IN PROGRESS:"));
QList<int> keys = m_cookieForToken.keys(); QList<int> keys = m_cookieForToken.keys();
qSort(keys); qSort(keys);
bool killIt = false;
foreach (int key, keys) { foreach (int key, keys) {
const GdbCommand &cmd = m_cookieForToken[key]; const GdbCommand &cmd = m_cookieForToken.value(key);
if (!(cmd.flags & NonCriticalResponse))
killIt = true;
debugMessage(_(" %1: %2 => %3").arg(key).arg(cmd.command).arg(_(cmd.callbackName))); debugMessage(_(" %1: %2 => %3").arg(key).arg(cmd.command).arg(_(cmd.callbackName)));
} }
// This is an entirely undefined state, so we just pull the emergency brake. if (killIt) {
setState(EngineShuttingDown, true); debugMessage(_("TIMED OUT WAITING FOR GDB REPLY. COMMANDS STILL IN PROGRESS:"));
m_gdbProc.kill(); int timeOut = m_commandTimer->interval();
//m_commandTimer->stop();
QString msg = tr("The gdb process has not produced any response "
"to a command within %1 seconds. This may been it is stuck "
"in an endless loop or taking longer than expected to perform "
"the operation it was reqested.\nYou have a choice of waiting "
"longer or abort debugging.").arg(timeOut);
QMessageBox *mb = showMessageBox(QMessageBox::Critical,
tr("Gdb not responding"), msg,
QMessageBox::Ok | QMessageBox::Cancel);
mb->button(QMessageBox::Cancel)->setText(tr("Give gdb more time"));
mb->button(QMessageBox::Ok)->setText(tr("Stop debugging"));
if (mb->exec() == QMessageBox::Ok) {
debugMessage(_("KILLING DEBUGGER AS REQUESTED BY USER"));
// This is an undefined state, so we just pull the emergency brake.
manager()->watchHandler()->endCycle();
setState(EngineShuttingDown, true);
m_gdbProc.kill();
} else {
debugMessage(_("CONTINUE DEBUGGER AS REQUESTED BY USER"));
}
}
} }
void GdbEngine::handleResultRecord(GdbResponse *response) void GdbEngine::handleResultRecord(GdbResponse *response)
@@ -2960,7 +2989,7 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
<<',' << addr << ',' << (dumpChildren ? "1" : "0") <<',' << addr << ',' << (dumpChildren ? "1" : "0")
<< ',' << extraArgs.join(QString(_c(','))) << ')'; << ',' << extraArgs.join(QString(_c(','))) << ')';
postCommand(cmd, WatchUpdate | EmbedToken); postCommand(cmd, WatchUpdate | EmbedToken | NonCriticalResponse);
showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000); showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000);
@@ -4347,6 +4376,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
SLOT(readGdbStandardError())); SLOT(readGdbStandardError()));
debugMessage(_("GDB STARTED, INITIALIZING IT")); debugMessage(_("GDB STARTED, INITIALIZING IT"));
m_commandTimer->setInterval(commandTimeoutTime());
postCommand(_("show version"), CB(handleShowVersion)); postCommand(_("show version"), CB(handleShowVersion));
postCommand(_("-interpreter-exec console \"help bb\""), postCommand(_("-interpreter-exec console \"help bb\""),
@@ -4573,9 +4603,10 @@ void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const
opts->push_back(new TrkOptionsPage(m_trkOptions)); opts->push_back(new TrkOptionsPage(m_trkOptions));
} }
void GdbEngine::showMessageBox(int icon, const QString &title, const QString &text) QMessageBox * GdbEngine::showMessageBox(int icon, const QString &title,
const QString &text, int buttons)
{ {
m_manager->showMessageBox(icon, title, text); return m_manager->showMessageBox(icon, title, text, buttons);
} }
bool GdbEngine::isSynchroneous() const bool GdbEngine::isSynchroneous() const

View File

@@ -47,11 +47,12 @@
#include <QtCore/QVariant> #include <QtCore/QVariant>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAction;
class QAbstractItemModel; class QAbstractItemModel;
class QAction;
class QMainWindow;
class QMessageBox;
class QTimer; class QTimer;
class QWidget; class QWidget;
class QMainWindow;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Debugger { namespace Debugger {
@@ -176,10 +177,11 @@ private: ////////// Gdb Command Management //////////
Discardable = 2, // No need to wait for the reply before continuing inferior Discardable = 2, // No need to wait for the reply before continuing inferior
RebuildModel = 4, // Trigger model rebuild when no such commands are pending any more RebuildModel = 4, // Trigger model rebuild when no such commands are pending any more
WatchUpdate = Discardable | RebuildModel, WatchUpdate = Discardable | RebuildModel,
EmbedToken = 8, // Expand %1 in the command to the command token NonCriticalResponse = 8, // We can live without recieving an answer
RunRequest = 16, // Callback expects GdbResultRunning instead of GdbResultDone RunRequest = 16, // Callback expects GdbResultRunning instead of GdbResultDone
ExitRequest = 32, // Callback expects GdbResultExit instead of GdbResultDone ExitRequest = 32, // Callback expects GdbResultExit instead of GdbResultDone
LosesChild = 64 // Auto-set inferior shutdown related states LosesChild = 64, // Auto-set inferior shutdown related states
EmbedToken = 128 // Expand %1 in the command to the command token
}; };
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag) Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
private: private:
@@ -233,6 +235,7 @@ private: ////////// Gdb Command Management //////////
void setTokenBarrier(); void setTokenBarrier();
QHash<int, GdbCommand> m_cookieForToken; QHash<int, GdbCommand> m_cookieForToken;
int commandTimeoutTime() const;
QTimer *m_commandTimer; QTimer *m_commandTimer;
QByteArray m_pendingConsoleStreamOutput; QByteArray m_pendingConsoleStreamOutput;
@@ -476,7 +479,8 @@ private: ////////// Dumper Management //////////
private: ////////// Convenience Functions ////////// private: ////////// Convenience Functions //////////
QString errorMessage(QProcess::ProcessError error); QString errorMessage(QProcess::ProcessError error);
void showMessageBox(int icon, const QString &title, const QString &text); QMessageBox *showMessageBox(int icon, const QString &title, const QString &text,
int buttons = 0);
void debugMessage(const QString &msg); void debugMessage(const QString &msg);
QMainWindow *mainWindow() const; QMainWindow *mainWindow() const;
}; };