forked from qt-creator/qt-creator
debugger: gracefully handle commands that might not produce output
This commit is contained in:
@@ -1551,13 +1551,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
|
||||||
|
@@ -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
|
||||||
@@ -180,7 +181,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;
|
||||||
|
|
||||||
|
@@ -811,19 +811,47 @@ 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) {
|
||||||
|
debugMessage(_("TIMED OUT WAITING FOR GDB REPLY. COMMANDS STILL IN PROGRESS:"));
|
||||||
|
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();
|
manager()->watchHandler()->endCycle();
|
||||||
m_gdbProc.kill();
|
m_gdbProc.kill();
|
||||||
|
} else {
|
||||||
|
debugMessage(_("CONTINUE DEBUGGER AS REQUESTED BY USER"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleResultRecord(GdbResponse *response)
|
void GdbEngine::handleResultRecord(GdbResponse *response)
|
||||||
@@ -2969,7 +2997,7 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
|
|||||||
protocol << ",0," << addr << ',' << (dumpChildren ? "1" : "0")
|
protocol << ",0," << addr << ',' << (dumpChildren ? "1" : "0")
|
||||||
<< ',' << extraArgs.join(QString(_c(','))) << ')';
|
<< ',' << extraArgs.join(QString(_c(','))) << ')';
|
||||||
|
|
||||||
postCommand(cmd, WatchUpdate);
|
postCommand(cmd, WatchUpdate | NonCriticalResponse);
|
||||||
|
|
||||||
showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000);
|
showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000);
|
||||||
|
|
||||||
@@ -4388,13 +4416,14 @@ 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"));
|
||||||
int timeOut = theDebuggerAction(GdbWatchdogTimeout)->value().toInt();
|
m_commandTimer->setInterval(commandTimeoutTime());
|
||||||
m_commandTimer->setInterval(1000 * qMax(20, timeOut));
|
|
||||||
|
|
||||||
postCommand(_("show version"), CB(handleShowVersion));
|
postCommand(_("show version"), CB(handleShowVersion));
|
||||||
|
|
||||||
postCommand(_("python execfile('%1dumper.py')").arg(dumperSourcePath));
|
postCommand(_("python execfile('%1dumper.py')").arg(dumperSourcePath),
|
||||||
postCommand(_("python execfile('%1gdbmacros.py')").arg(dumperSourcePath));
|
NonCriticalResponse);
|
||||||
|
postCommand(_("python execfile('%1gdbmacros.py')").arg(dumperSourcePath),
|
||||||
|
NonCriticalResponse);
|
||||||
|
|
||||||
postCommand(_("-interpreter-exec console \"help bb\""),
|
postCommand(_("-interpreter-exec console \"help bb\""),
|
||||||
CB(handleIsSynchroneous));
|
CB(handleIsSynchroneous));
|
||||||
@@ -4620,9 +4649,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
|
||||||
|
@@ -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 {
|
||||||
@@ -177,6 +178,7 @@ 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,
|
||||||
|
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
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user