forked from qt-creator/qt-creator
		
	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:
		@@ -617,7 +617,7 @@ void GdbEngine::readGdbStandardError()
 | 
			
		||||
 | 
			
		||||
void GdbEngine::readGdbStandardOutput()
 | 
			
		||||
{
 | 
			
		||||
    if (m_commandTimer->isActive())
 | 
			
		||||
    if (m_commandTimer->isActive()) 
 | 
			
		||||
        m_commandTimer->start(); // Retrigger
 | 
			
		||||
 | 
			
		||||
    int newstart = 0;
 | 
			
		||||
@@ -816,19 +816,48 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0)
 | 
			
		||||
        setState(InferiorShuttingDown);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int GdbEngine::commandTimeoutTime() const
 | 
			
		||||
{
 | 
			
		||||
    int time = theDebuggerAction(GdbWatchdogTimeout)->value().toInt();
 | 
			
		||||
    return 1000 * qMax(20, time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GdbEngine::commandTimeout()
 | 
			
		||||
{
 | 
			
		||||
    // FIXME this needs a proper message box
 | 
			
		||||
    debugMessage(_("TIMED OUT WAITING FOR GDB REPLY. COMMANDS STILL IN PROGRESS:"));
 | 
			
		||||
    qDebug("TIMEOUT");
 | 
			
		||||
    QList<int> keys = m_cookieForToken.keys();
 | 
			
		||||
    qSort(keys);
 | 
			
		||||
    bool killIt = false;
 | 
			
		||||
    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)));
 | 
			
		||||
    }
 | 
			
		||||
    // This is an entirely undefined state, so we just pull the emergency brake.
 | 
			
		||||
    setState(EngineShuttingDown, true);
 | 
			
		||||
    m_gdbProc.kill();
 | 
			
		||||
    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();
 | 
			
		||||
            setState(EngineShuttingDown, true);
 | 
			
		||||
            m_gdbProc.kill();
 | 
			
		||||
        } else {
 | 
			
		||||
            debugMessage(_("CONTINUE DEBUGGER AS REQUESTED BY USER"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GdbEngine::handleResultRecord(GdbResponse *response)
 | 
			
		||||
@@ -2960,7 +2989,7 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
 | 
			
		||||
            <<',' <<  addr << ',' << (dumpChildren ? "1" : "0")
 | 
			
		||||
            << ',' << extraArgs.join(QString(_c(','))) <<  ')';
 | 
			
		||||
 | 
			
		||||
    postCommand(cmd, WatchUpdate | EmbedToken);
 | 
			
		||||
    postCommand(cmd, WatchUpdate | EmbedToken | NonCriticalResponse);
 | 
			
		||||
 | 
			
		||||
    showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000);
 | 
			
		||||
 | 
			
		||||
@@ -4347,6 +4376,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
 | 
			
		||||
        SLOT(readGdbStandardError()));
 | 
			
		||||
 | 
			
		||||
    debugMessage(_("GDB STARTED, INITIALIZING IT"));
 | 
			
		||||
    m_commandTimer->setInterval(commandTimeoutTime());
 | 
			
		||||
 | 
			
		||||
    postCommand(_("show version"), CB(handleShowVersion));
 | 
			
		||||
    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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
@@ -47,11 +47,12 @@
 | 
			
		||||
#include <QtCore/QVariant>
 | 
			
		||||
 | 
			
		||||
QT_BEGIN_NAMESPACE
 | 
			
		||||
class QAction;
 | 
			
		||||
class QAbstractItemModel;
 | 
			
		||||
class QAction;
 | 
			
		||||
class QMainWindow;
 | 
			
		||||
class QMessageBox;
 | 
			
		||||
class QTimer;
 | 
			
		||||
class QWidget;
 | 
			
		||||
class QMainWindow;
 | 
			
		||||
QT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
namespace Debugger {
 | 
			
		||||
@@ -176,10 +177,11 @@ private: ////////// Gdb Command Management //////////
 | 
			
		||||
        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
 | 
			
		||||
        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
 | 
			
		||||
        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)
 | 
			
		||||
    private:
 | 
			
		||||
@@ -233,6 +235,7 @@ private: ////////// Gdb Command Management //////////
 | 
			
		||||
    void setTokenBarrier();
 | 
			
		||||
 | 
			
		||||
    QHash<int, GdbCommand> m_cookieForToken;
 | 
			
		||||
    int commandTimeoutTime() const;
 | 
			
		||||
    QTimer *m_commandTimer;
 | 
			
		||||
 | 
			
		||||
    QByteArray m_pendingConsoleStreamOutput;
 | 
			
		||||
@@ -476,7 +479,8 @@ private: ////////// Dumper Management //////////
 | 
			
		||||
private: ////////// Convenience Functions //////////
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    QMainWindow *mainWindow() const;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user