diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index 4d820b3cd8b9fb056f595b00d3784c660748fd59..eb022abdd859d21fbce98a970672d31f156e163a 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -98,99 +98,12 @@ static inline QString _(const char *s) { return QString::fromLatin1(s); }
 
 static const QString tooltipIName = _("tooltip");
 
-///////////////////////////////////////////////////////////////////////
-//
-// GdbCommandType
-//
-///////////////////////////////////////////////////////////////////////
-
-enum GdbCommandType
-{
-    GdbInvalidCommand = 0,
-
-    GdbShowVersion = 100,
-    GdbFileExecAndSymbols,
-    //GdbQueryPwd,
-    GdbQuerySources,
-    GdbAsyncOutput2,
-    GdbStart,
-    GdbExit,
-    GdbAttached,
-    GdbStubAttached,
-    GdbExecRun,
-    GdbExecRunToFunction,
-    GdbExecStep,
-    GdbExecNext,
-    GdbExecStepI,
-    GdbExecNextI,
-    GdbExecContinue,
-    GdbExecFinish,
-    //GdbExecJumpToLine,
-    GdbExecInterrupt,
-    GdbInfoShared,
-    GdbInfoProc,
-    GdbInfoThreads,
-    GdbQueryDebuggingHelper,
-    GdbTemporaryContinue,
-    GdbTargetCore,
-
-    BreakCondition = 200,
-    BreakEnablePending,
-    BreakSetAnnotate,
-    BreakDelete,
-    BreakEnable,
-    BreakDisable,
-    BreakList,
-    BreakIgnore,
-    BreakInfo,
-    BreakInsert,
-    BreakInsert1,
-
-    DisassemblerList = 300,
-
-    ModulesList = 400,
-
-    RegisterListNames = 500,
-    RegisterListValues,
-
-    StackSelectThread = 600,
-    StackListThreads,
-    StackListFrames,
-    StackListLocals,
-    StackListArguments,
-
-    WatchVarAssign = 700,             // data changed by user
-    WatchVarListChildren,
-    WatchVarCreate,
-    WatchEvaluateExpression,
-    WatchToolTip,
-    WatchDebuggingHelperSetup,
-    WatchDebuggingHelperValue1,           // waiting for gdb ack
-    WatchDebuggingHelperValue2,           // waiting for actual data
-    WatchDebuggingHelperValue3,           // macro based
-    WatchDebuggingHelperEditValue,
-};
-
 static int &currentToken()
 {
     static int token = 0;
     return token;
 }
 
-static bool isSkippable(int type)
-{
-    return type == RegisterListValues
-        && type == StackListThreads
-        && type == StackListFrames
-        && type == StackListLocals
-        && type == StackListArguments
-        && type == WatchVarAssign
-        && type == WatchVarListChildren
-        && type == WatchVarCreate
-        && type == WatchEvaluateExpression
-        && type == WatchToolTip;
-}
-
 ///////////////////////////////////////////////////////////////////////
 //
 // GdbEngine
@@ -559,7 +472,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
     }
 }
 
-void GdbEngine::handleStubAttached()
+void GdbEngine::handleStubAttached(const GdbResultRecord &, const QVariant &)
 {
     qq->notifyInferiorStopped();
     m_waitingForBreakpointSynchronizationToContinue = true;
@@ -570,7 +483,7 @@ void GdbEngine::stubStarted()
 {
     q->m_attachedPID = m_stubProc.applicationPID();
     qq->notifyInferiorPidChanged(q->m_attachedPID);
-    sendCommand(_("attach ") + QString::number(q->m_attachedPID), GdbStubAttached);
+    execCommand(_("attach ") + QString::number(q->m_attachedPID), handleStubAttached);
 }
 
 void GdbEngine::stubError(const QString &msg)
@@ -645,36 +558,32 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
     qq->notifyInferiorPidChanged(pid);
 }
 
-void GdbEngine::sendSynchronizedCommand(const QString & command,
-    int type, const QVariant &cookie, StopNeeded needStop)
-{
-    sendCommand(command, type, cookie, needStop, Synchronized);
-}
-
-void GdbEngine::sendCommand(const QString &command, int type,
-    const QVariant &cookie, StopNeeded needStop, Synchronization synchronized)
+void GdbEngine::execCommandInternal(const QString &command, GdbCommandFlags flags,
+                                    GdbCommandCallback callback, const char *callbackName,
+                                    const QVariant &cookie)
 {
     if (m_gdbProc.state() == QProcess::NotRunning) {
         debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + command);
         return;
     }
 
-    if (synchronized) {
+    if (flags & RebuildModel) {
         ++m_pendingRequests;
-        PENDING_DEBUG("   TYPE " << type << " INCREMENTS PENDING TO: "
+        PENDING_DEBUG("   CALLBACK " << callbackName << " INCREMENTS PENDING TO: "
             << m_pendingRequests << command);
     } else {
-        PENDING_DEBUG("   UNKNOWN TYPE " << type << " LEAVES PENDING AT: "
+        PENDING_DEBUG("   UNKNOWN CALLBACK " << callbackName << " LEAVES PENDING AT: "
             << m_pendingRequests << command);
     }
 
-    GdbCookie cmd;
-    cmd.synchronized = synchronized;
+    GdbCommand cmd;
     cmd.command = command;
-    cmd.type = type;
+    cmd.flags = flags;
+    cmd.callback = callback;
+    cmd.callbackName = callbackName;
     cmd.cookie = cookie;
 
-    if (needStop && q->status() != DebuggerInferiorStopped
+    if ((flags & NeedsStop) && q->status() != DebuggerInferiorStopped
             && q->status() != DebuggerProcessStartingUp) {
         // queue the commands that we cannot send at once
         QTC_ASSERT(q->status() == DebuggerInferiorRunning,
@@ -684,19 +593,29 @@ void GdbEngine::sendCommand(const QString &command, int type,
         m_commandsToRunOnTemporaryBreak.append(cmd);
         interruptInferior();
     } else if (!command.isEmpty()) {
-        ++currentToken();
-        m_cookieForToken[currentToken()] = cmd;
-        cmd.command = QString::number(currentToken()) + cmd.command;
-        if (cmd.command.contains(__("%1")))
-            cmd.command = cmd.command.arg(currentToken());
-
-        m_gdbProc.write(cmd.command.toLatin1() + "\r\n");
-        //emit gdbInputAvailable(QString(), "         " +  currentTime());
-        //emit gdbInputAvailable(QString(), "[" + currentTime() + "]    " + cmd.command);
-        emit gdbInputAvailable(QString(), cmd.command);
+        flushCommand(cmd);
     }
 }
 
+void GdbEngine::flushCommand(GdbCommand &cmd)
+{
+    ++currentToken();
+    m_cookieForToken[currentToken()] = cmd;
+    cmd.command = QString::number(currentToken()) + cmd.command;
+    if (cmd.command.contains(__("%1")))
+        cmd.command = cmd.command.arg(currentToken());
+
+    m_gdbProc.write(cmd.command.toLatin1() + "\r\n");
+    //emit gdbInputAvailable(QString(), "         " +  currentTime());
+    //emit gdbInputAvailable(QString(), "[" + currentTime() + "]    " + cmd.command);
+    emit gdbInputAvailable(QString(), cmd.command);
+}
+
+void GdbEngine::sendCommand(const QString &command, GdbCommandFlags flags)
+{
+    execCommandInternal(command, flags, 0, 0, QVariant());
+}
+
 void GdbEngine::handleResultRecord(const GdbResultRecord &record)
 {
     //qDebug() << "TOKEN: " << record.token
@@ -708,9 +627,9 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
     if (token == -1)
         return;
 
-    GdbCookie cmd = m_cookieForToken.take(token);
+    GdbCommand cmd = m_cookieForToken.take(token);
 
-    if (record.token < m_oldestAcceptableToken && isSkippable(cmd.type)) {
+    if (record.token < m_oldestAcceptableToken && (cmd.flags & Discardable)) {
         //qDebug() << "### SKIPPING OLD RESULT " << record.toString();
         //QMessageBox::information(m_mainWindow, tr("Skipped"), "xxx");
         return;
@@ -725,10 +644,10 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
 
     // << "\n data: " << record.data.toString(true);
 
-    if (cmd.type != GdbInvalidCommand)
-        handleResult(record, cmd.type, cmd.cookie);
+    if (cmd.callback)
+        (this->*(cmd.callback))(record, cmd.cookie);
 
-    if (cmd.synchronized) {
+    if (cmd.flags & RebuildModel) {
         --m_pendingRequests;
         PENDING_DEBUG("   TYPE " << cmd.type << " DECREMENTS PENDING TO: "
             << m_pendingRequests << cmd.command);
@@ -742,176 +661,6 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
     }
 }
 
-void GdbEngine::handleResult(const GdbResultRecord & record, int type,
-    const QVariant & cookie)
-{
-    switch (type) {
-        case GdbStubAttached:
-            handleStubAttached();
-            break;
-        case GdbExecNext:
-        case GdbExecStep:
-        case GdbExecNextI:
-        case GdbExecStepI:
-        case GdbExecContinue:
-        case GdbExecFinish:
-            // evil code sharing
-            handleExecRun(record);
-            break;
-
-        case GdbStart:
-            handleStart(record);
-            break;
-        case GdbAttached:
-            handleAttach();
-            break;
-        case GdbInfoProc:
-            handleInfoProc(record);
-            break;
-        case GdbInfoThreads:
-            handleInfoThreads(record);
-            break;
-        case GdbExit:
-            handleExit(record);
-            break;
-
-        case GdbShowVersion:
-            handleShowVersion(record);
-            break;
-        case GdbFileExecAndSymbols:
-            handleFileExecAndSymbols(record);
-            break;
-        case GdbExecRunToFunction:
-            // that should be "^running". We need to handle the resulting
-            // "Stopped"
-            //handleExecRunToFunction(record);
-            break;
-        case GdbExecInterrupt:
-            qq->notifyInferiorStopped();
-            break;
-#if 0
-        case GdbExecJumpToLine:
-            handleExecJumpToLine(record);
-            break;
-#endif
-#if 0
-        case GdbQueryPwd:
-            handleQueryPwd(record);
-            break;
-#endif
-        case GdbQuerySources:
-            handleQuerySources(record);
-            break;
-        case GdbAsyncOutput2:
-            handleAsyncOutput2(cookie.value<GdbMi>());
-            break;
-        case GdbInfoShared:
-            handleInfoShared(record);
-            break;
-        case GdbQueryDebuggingHelper:
-            handleQueryDebuggingHelper(record);
-            break;
-        case GdbTemporaryContinue:
-            continueInferior();
-            q->showStatusMessage(tr("Continuing after temporary stop."));
-            break;
-        case GdbTargetCore:
-            handleTargetCore(record);
-            break;
-
-        case BreakList:
-            handleBreakList(record);
-            break;
-        case BreakInsert:
-            handleBreakInsert(record, cookie.toInt());
-            break;
-        case BreakInsert1:
-            handleBreakInsert1(record, cookie.toInt());
-            break;
-        case BreakInfo:
-            handleBreakInfo(record, cookie.toInt());
-            break;
-        case BreakEnablePending:
-        case BreakDelete:
-        case BreakEnable:
-        case BreakDisable:
-            // nothing
-            break;
-        case BreakIgnore:
-            handleBreakIgnore(record, cookie.toInt());
-            break;
-        case BreakCondition:
-            handleBreakCondition(record, cookie.toInt());
-            break;
-
-        case DisassemblerList:
-            handleDisassemblerList(record, cookie.toString());
-            break;
-
-        case ModulesList:
-            handleModulesList(record);
-            break;
-
-        case RegisterListNames:
-            handleRegisterListNames(record);
-            break;
-        case RegisterListValues:
-            handleRegisterListValues(record);
-            break;
-
-        case StackListFrames:
-            handleStackListFrames(record, cookie.toBool());
-            break;
-        case StackListThreads:
-            handleStackListThreads(record, cookie.toInt());
-            break;
-        case StackSelectThread:
-            handleStackSelectThread(record, cookie.toInt());
-            break;
-        case StackListLocals:
-            handleStackListLocals(record);
-            break;
-        case StackListArguments:
-            handleStackListArguments(record);
-            break;
-
-        case WatchVarListChildren:
-            handleVarListChildren(record, cookie.value<WatchData>());
-            break;
-        case WatchVarCreate:
-            handleVarCreate(record, cookie.value<WatchData>());
-            break;
-        case WatchVarAssign:
-            handleVarAssign();
-            break;
-        case WatchEvaluateExpression:
-            handleEvaluateExpression(record, cookie.value<WatchData>());
-            break;
-        case WatchToolTip:
-            handleToolTip(record, cookie.toByteArray());
-            break;
-        case WatchDebuggingHelperValue1:
-            handleDebuggingHelperValue1(record, cookie.value<WatchData>());
-            break;
-        case WatchDebuggingHelperValue2:
-            handleDebuggingHelperValue2(record, cookie.value<WatchData>());
-            break;
-
-        case WatchDebuggingHelperValue3:
-            handleDebuggingHelperValue3(record, cookie.value<WatchData>());
-            break;
-
-        case WatchDebuggingHelperSetup:
-            handleDebuggingHelperSetup(record);
-            break;
-
-        default:
-            debugMessage(_("FIXME: GdbEngine::handleResult: "
-                "should not happen %1").arg(type));
-            break;
-    }
-}
-
 void GdbEngine::executeDebuggerCommand(const QString &command)
 {
     if (m_gdbProc.state() == QProcess::NotRunning) {
@@ -922,10 +671,8 @@ void GdbEngine::executeDebuggerCommand(const QString &command)
     m_gdbProc.write(command.toLatin1() + "\r\n");
 }
 
-void GdbEngine::handleTargetCore(const GdbResultRecord &record)
+void GdbEngine::handleTargetCore(const GdbResultRecord &, const QVariant &)
 {
-    Q_UNUSED(record);
-
     qq->notifyInferiorStopped();
     q->showStatusMessage(tr("Core file loaded."));
 
@@ -939,7 +686,7 @@ void GdbEngine::handleTargetCore(const GdbResultRecord &record)
 
     reloadStack();
     if (supportsThreads())
-        sendSynchronizedCommand(_("-thread-list-ids"), StackListThreads, 0);
+        execCommandFC(_("-thread-list-ids"), handleStackListThreads, WatchUpdate, 0);
 
     //
     // Disassembler
@@ -1007,7 +754,7 @@ void GdbEngine::handleQueryPwd(const GdbResultRecord &record)
 }
 #endif
 
-void GdbEngine::handleQuerySources(const GdbResultRecord &record)
+void GdbEngine::handleQuerySources(const GdbResultRecord &record, const QVariant &)
 {
     if (record.resultClass == GdbResultDone) {
         QMap<QString, QString> oldShortToFull = m_shortToFullName;
@@ -1034,7 +781,7 @@ void GdbEngine::handleQuerySources(const GdbResultRecord &record)
     }
 }
 
-void GdbEngine::handleInfoThreads(const GdbResultRecord &record)
+void GdbEngine::handleInfoThreads(const GdbResultRecord &record, const QVariant &)
 {
     if (record.resultClass == GdbResultDone) {
         // FIXME: use something more robust
@@ -1047,7 +794,7 @@ void GdbEngine::handleInfoThreads(const GdbResultRecord &record)
     }
 }
 
-void GdbEngine::handleInfoProc(const GdbResultRecord &record)
+void GdbEngine::handleInfoProc(const GdbResultRecord &record, const QVariant &)
 {
     if (record.resultClass == GdbResultDone) {
         #if defined(Q_OS_MAC)
@@ -1065,11 +812,11 @@ void GdbEngine::handleInfoProc(const GdbResultRecord &record)
     }
 }
 
-void GdbEngine::handleInfoShared(const GdbResultRecord &record)
+void GdbEngine::handleInfoShared(const GdbResultRecord &record, const QVariant &cookie)
 {
     if (record.resultClass == GdbResultDone) {
         // let the modules handler do the parsing
-        handleModulesList(record);
+        handleModulesList(record, cookie);
     }
 }
 
@@ -1100,7 +847,7 @@ void GdbEngine::handleExecJumpToLine(const GdbResultRecord &record)
 }
 #endif
 
-void GdbEngine::handleExecRunToFunction(const GdbResultRecord &record)
+void GdbEngine::handleExecRunToFunction(const GdbResultRecord &record, const QVariant &)
 {
     // FIXME: remove this special case as soon as there's a real
     // reason given when the temporary breakpoint is hit.
@@ -1144,13 +891,13 @@ static bool isStoppedReason(const QByteArray &reason)
 void GdbEngine::handleAqcuiredInferior()
 {
     #if defined(Q_OS_WIN)
-    sendCommand(_("info thread"), GdbInfoThreads);
+    execCommand(_("info thread"), handleInfoThreads);
     #endif
     #if defined(Q_OS_LINUX)
-    sendCommand(_("info proc"), GdbInfoProc);
+    execCommand(_("info proc"), handleInfoProc);
     #endif
     #if defined(Q_OS_MAC)
-    sendCommand(_("info pid"), GdbInfoProc, QVariant(), NeedsStop);
+    execCommandF(_("info pid"), handleInfoProc, NeedsStop);
     #endif
     if (theDebuggerBoolSetting(ListSourceFiles))
         reloadSourceFiles();
@@ -1180,6 +927,12 @@ void GdbEngine::handleAqcuiredInferior()
     attemptBreakpointSynchronization();
 }
 
+void GdbEngine::handleAutoContinue(const GdbResultRecord &, const QVariant &)
+{
+    continueInferior();
+    q->showStatusMessage(tr("Continuing after temporary stop."));
+}
+
 void GdbEngine::handleAsyncOutput(const GdbMi &data)
 {
     const QByteArray &reason = data.findChild("reason").data();
@@ -1197,7 +950,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
             msg = tr("Program exited normally");
         }
         q->showStatusMessage(msg);
-        sendCommand(_("-gdb-exit"), GdbExit);
+        execCommand(_("-gdb-exit"), handleExit);
         return;
     }
 
@@ -1226,13 +979,13 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
         qq->notifyInferiorStopped();
         q->showStatusMessage(tr("Temporarily stopped."));
         // FIXME: racy
-        foreach (const GdbCookie &cmd, m_commandsToRunOnTemporaryBreak) {
+        while (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
+            GdbCommand cmd = m_commandsToRunOnTemporaryBreak.takeFirst();
             debugMessage(_("RUNNING QUEUED COMMAND %1 %2")
-                .arg(cmd.command).arg(cmd.type));
-            sendCommand(cmd.command, cmd.type, cmd.cookie);
+                .arg(cmd.command).arg(_(cmd.callbackName)));
+            flushCommand(cmd);
         }
-        sendCommand(_("p temporaryStop"), GdbTemporaryContinue);
-        m_commandsToRunOnTemporaryBreak.clear();
+        execCommand(_("p temporaryStop"), handleAutoContinue);
         q->showStatusMessage(tr("Handling queued commands."));
         return;
     }
@@ -1312,9 +1065,9 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
             QApplication::alert(q->mainWindow(), 3000);
             if (theDebuggerAction(ListSourceFiles)->value().toBool())
                 reloadSourceFiles();
-            sendCommand(_("-break-list"), BreakList);
+            execCommand(_("-break-list"), handleBreakList);
             QVariant var = QVariant::fromValue<GdbMi>(data);
-            sendCommand(_("p 0"), GdbAsyncOutput2, var);  // dummy
+            execCommandFC(_("p 0"), handleAsyncOutput2, NoFlags, var);  // dummy
         } else {
 #ifdef Q_OS_LINUX
             // For some reason, attaching to a stopped process causes *two* stops
@@ -1365,7 +1118,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
 void GdbEngine::reloadFullStack()
 {
     QString cmd = _("-stack-list-frames");
-    sendSynchronizedCommand(cmd, StackListFrames, true);
+    execCommandFC(cmd, handleStackListFrames, WatchUpdate, true);
 }
 
 void GdbEngine::reloadStack()
@@ -1373,7 +1126,12 @@ void GdbEngine::reloadStack()
     QString cmd = _("-stack-list-frames");
     if (int stackDepth = theDebuggerAction(MaximalStackDepth)->value().toInt())
         cmd += _(" 0 ") + QString::number(stackDepth);
-    sendSynchronizedCommand(cmd, StackListFrames, false);
+    execCommandFC(cmd, handleStackListFrames, WatchUpdate, false);
+}
+
+void GdbEngine::handleAsyncOutput2(const GdbResultRecord &, const QVariant &cookie)
+{
+    handleAsyncOutput2(cookie.value<GdbMi>());
 }
 
 void GdbEngine::handleAsyncOutput2(const GdbMi &data)
@@ -1389,7 +1147,7 @@ void GdbEngine::handleAsyncOutput2(const GdbMi &data)
     int currentId = data.findChild("thread-id").data().toInt();
     reloadStack();
     if (supportsThreads())
-        sendSynchronizedCommand(_("-thread-list-ids"), StackListThreads, currentId);
+        execCommandFC(_("-thread-list-ids"), handleStackListThreads, WatchUpdate, currentId);
 
     //
     // Disassembler
@@ -1409,7 +1167,7 @@ void GdbEngine::handleAsyncOutput2(const GdbMi &data)
     qq->reloadRegisters();
 }
 
-void GdbEngine::handleShowVersion(const GdbResultRecord &response)
+void GdbEngine::handleShowVersion(const GdbResultRecord &response, const QVariant &)
 {
     //qDebug () << "VERSION 2:" << response.data.findChild("consolestreamoutput").data();
     //qDebug () << "VERSION:" << response.toString();
@@ -1448,8 +1206,7 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response)
     }
 }
 
-void GdbEngine::handleFileExecAndSymbols
-    (const GdbResultRecord &response)
+void GdbEngine::handleFileExecAndSymbols(const GdbResultRecord &response, const QVariant &)
 {
     if (response.resultClass == GdbResultDone) {
         //m_breakHandler->clearBreakMarkers();
@@ -1462,7 +1219,7 @@ void GdbEngine::handleFileExecAndSymbols
     }
 }
 
-void GdbEngine::handleExecRun(const GdbResultRecord &response)
+void GdbEngine::handleExecRun(const GdbResultRecord &response, const QVariant &)
 {
     if (response.resultClass == GdbResultRunning) {
         qq->notifyInferiorRunning();
@@ -1556,7 +1313,7 @@ void GdbEngine::exitDebugger()
             sendCommand(_("detach"));
         else
             sendCommand(_("kill"));
-        sendCommand(_("-gdb-exit"), GdbExit);
+        execCommand(_("-gdb-exit"), handleExit);
         // 20s can easily happen when loading webkit debug information
         m_gdbProc.waitForFinished(20000);
         if (m_gdbProc.state() != QProcess::Running) {
@@ -1645,7 +1402,7 @@ bool GdbEngine::startDebugger()
 
     q->showStatusMessage(tr("Gdb Running..."));
 
-    sendCommand(_("show version"), GdbShowVersion);
+    execCommand(_("show version"), handleShowVersion);
     //sendCommand(_("-enable-timings");
     sendCommand(_("set print static-members off")); // Seemingly doesn't work.
     //sendCommand(_("define hook-stop\n-thread-list-ids\n-stack-list-frames\nend"));
@@ -1659,9 +1416,9 @@ bool GdbEngine::startDebugger()
     //sendCommand(_("set print pretty on"));
     //sendCommand(_("set confirm off"));
     //sendCommand(_("set pagination off"));
-    sendCommand(_("set breakpoint pending on"), BreakEnablePending);
+    sendCommand(_("set breakpoint pending on"));
     sendCommand(_("set print elements 10000"));
-    sendCommand(_("-data-list-register-names"), RegisterListNames);
+    execCommand(_("-data-list-register-names"), handleRegisterListNames);
 
     //sendCommand(_("set substitute-path /var/tmp/qt-x11-src-4.5.0 "
     //    "/home/sandbox/qtsdk-2009.01/qt"));
@@ -1689,7 +1446,7 @@ bool GdbEngine::startDebugger()
     //sendCommand(_("handle SIGTERM pass nostop print"));
 
     sendCommand(_("set unwindonsignal on"));
-    //sendCommand(_("pwd", GdbQueryPwd));
+    //execCommand(_("pwd", handleQueryPwd));
     sendCommand(_("set width 0"));
     sendCommand(_("set height 0"));
 
@@ -1722,7 +1479,7 @@ bool GdbEngine::startDebugger()
     }
 
     if (q->startMode() == AttachExternal) {
-        sendCommand(_("attach ") + QString::number(q->m_attachedPID), GdbAttached);
+        execCommand(_("attach ") + QString::number(q->m_attachedPID), handleAttach);
         qq->breakHandler()->removeAllBreakpoints();
     } else if (q->startMode() == AttachCore) {
         QFileInfo fi(q->m_executable);
@@ -1731,22 +1488,22 @@ bool GdbEngine::startDebugger()
         // quoting core name below fails in gdb 6.8-debian
         QString coreName = fi2.absoluteFilePath();
         sendCommand(_("-file-exec-and-symbols ") + fileName);
-        sendCommand(_("target core %1").arg(coreName), GdbTargetCore);
+        execCommand(_("target core ") + coreName, handleTargetCore);
         qq->breakHandler()->removeAllBreakpoints();
     } else if (q->startMode() == AttachRemote) {
         sendCommand(_("set architecture %1").arg(q->m_remoteArchitecture));
         sendCommand(_("target remote %1").arg(q->m_remoteChannel));
         qq->breakHandler()->setAllPending();
-        //sendCommand(_("info target"), GdbStart);
+        //execCommand(_("info target"), handleStart);
         qq->notifyInferiorRunningRequested();
-        sendCommand(_("-exec-continue"), GdbExecContinue);
+        execCommand(_("-exec-continue"), handleExecRun);
     } else if (q->m_useTerminal) {
         qq->breakHandler()->setAllPending();
     } else if (q->startMode() == StartInternal || q->startMode() == StartExternal) {
         QFileInfo fi(q->m_executable);
         QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
-        sendCommand(_("-file-exec-and-symbols ") + fileName, GdbFileExecAndSymbols);
-        //sendCommand(_("file ") + fileName, GdbFileExecAndSymbols);
+        execCommand(_("-file-exec-and-symbols ") + fileName, handleFileExecAndSymbols);
+        //execCommand(_("file ") + fileName, handleFileExecAndSymbols);
         #ifdef Q_OS_MAC
         sendCommand(_("sharedlibrary apply-load-rules all"));
         #endif
@@ -1754,7 +1511,7 @@ bool GdbEngine::startDebugger()
             sendCommand(_("-exec-arguments ") + q->m_processArgs.join(_(" ")));
         #ifndef Q_OS_MAC
         sendCommand(_("set auto-solib-add off"));
-        sendCommand(_("info target"), GdbStart);
+        execCommand(_("info target"), handleStart);
         #else
         // On MacOS, breaking in at the entry point wreaks havoc.
         sendCommand(_("tbreak main"));
@@ -1773,10 +1530,10 @@ void GdbEngine::continueInferior()
     q->resetLocation();
     setTokenBarrier();
     qq->notifyInferiorRunningRequested();
-    sendCommand(_("-exec-continue"), GdbExecContinue);
+    execCommand(_("-exec-continue"), handleExecRun);
 }
 
-void GdbEngine::handleStart(const GdbResultRecord &response)
+void GdbEngine::handleStart(const GdbResultRecord &response, const QVariant &)
 {
 #ifdef Q_OS_MAC
     Q_UNUSED(response);
@@ -1802,7 +1559,7 @@ void GdbEngine::handleStart(const GdbResultRecord &response)
 #endif
 }
 
-void GdbEngine::handleAttach()
+void GdbEngine::handleAttach(const GdbResultRecord &, const QVariant &)
 {
     qq->notifyInferiorStopped();
     q->showStatusMessage(tr("Attached to running process. Stopped."));
@@ -1819,7 +1576,7 @@ void GdbEngine::handleAttach()
 
     reloadStack();
     if (supportsThreads())
-        sendSynchronizedCommand(_("-thread-list-ids"), StackListThreads, 0);
+        execCommandFC(_("-thread-list-ids"), handleStackListThreads, WatchUpdate, 0);
 
     //
     // Disassembler
@@ -1834,9 +1591,8 @@ void GdbEngine::handleAttach()
     qq->reloadRegisters();
 }
 
-void GdbEngine::handleExit(const GdbResultRecord &response)
+void GdbEngine::handleExit(const GdbResultRecord &, const QVariant &)
 {
-    Q_UNUSED(response);
     q->showStatusMessage(tr("Debugger exited."));
 }
 
@@ -1844,35 +1600,35 @@ void GdbEngine::stepExec()
 {
     setTokenBarrier();
     qq->notifyInferiorRunningRequested();
-    sendCommand(_("-exec-step"), GdbExecStep);
+    execCommand(_("-exec-step"), handleExecRun);
 }
 
 void GdbEngine::stepIExec()
 {
     setTokenBarrier();
     qq->notifyInferiorRunningRequested();
-    sendCommand(_("-exec-step-instruction"), GdbExecStepI);
+    execCommand(_("-exec-step-instruction"), handleExecRun);
 }
 
 void GdbEngine::stepOutExec()
 {
     setTokenBarrier();
     qq->notifyInferiorRunningRequested();
-    sendCommand(_("-exec-finish"), GdbExecFinish);
+    execCommand(_("-exec-finish"), handleExecRun);
 }
 
 void GdbEngine::nextExec()
 {
     setTokenBarrier();
     qq->notifyInferiorRunningRequested();
-    sendCommand(_("-exec-next"), GdbExecNext);
+    execCommand(_("-exec-next"), handleExecRun);
 }
 
 void GdbEngine::nextIExec()
 {
     setTokenBarrier();
     qq->notifyInferiorRunningRequested();
-    sendCommand(_("-exec-next-instruction"), GdbExecNextI);
+    execCommand(_("-exec-next-instruction"), handleExecRun);
 }
 
 void GdbEngine::runToLineExec(const QString &fileName, int lineNumber)
@@ -1887,7 +1643,10 @@ void GdbEngine::runToFunctionExec(const QString &functionName)
     setTokenBarrier();
     sendCommand(_("-break-insert -t ") + functionName);
     qq->notifyInferiorRunningRequested();
-    sendCommand(_("-exec-continue"), GdbExecRunToFunction);
+    // that should be "^running". We need to handle the resulting
+    // "Stopped"
+    sendCommand(_("-exec-continue"));
+    //execCommand(_("-exec-continue"), handleExecRunToFunction);
 }
 
 void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
@@ -1925,18 +1684,9 @@ void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
 
 void GdbEngine::setTokenBarrier()
 {
-    foreach (const GdbCookie &cookie, m_cookieForToken) {
-        QTC_ASSERT(
-            cookie.synchronized
-                || cookie.type == GdbInvalidCommand
-                // FIXME: use something like "command classes" for these cases:
-                || cookie.type == GdbInfoProc
-                || cookie.type == GdbStubAttached
-                || cookie.type == ModulesList
-                || cookie.type == WatchDebuggingHelperSetup
-                || cookie.type == GdbQueryDebuggingHelper,
-            qDebug() << "CMD: " << cookie.command << "TYPE: " << cookie.type
-                << "SYNC: " << cookie.synchronized;
+    foreach (const GdbCommand &cookie, m_cookieForToken) {
+        QTC_ASSERT(!cookie.callback || (cookie.flags & Discardable),
+            qDebug() << "CMD: " << cookie.command << "CALLBACK: " << cookie.callbackName;
             return
         );
     }
@@ -2080,10 +1830,10 @@ void GdbEngine::sendInsertBreakpoint(int index)
     cmd += where;
 #endif
     debugMessage(_("Current state: %1").arg(q->status()));
-    sendCommand(cmd, BreakInsert, index, NeedsStop);
+    execCommandFC(cmd, handleBreakInsert, NeedsStop, index);
 }
 
-void GdbEngine::handleBreakList(const GdbResultRecord &record)
+void GdbEngine::handleBreakList(const GdbResultRecord &record, const QVariant &)
 {
     // 45^done,BreakpointTable={nr_rows="2",nr_cols="6",hdr=[
     // {width="3",alignment="-1",col_name="number",colhdr="Num"}, ...
@@ -2143,8 +1893,9 @@ void GdbEngine::handleBreakList(const GdbMi &table)
 }
 
 
-void GdbEngine::handleBreakIgnore(const GdbResultRecord &record, int index)
+void GdbEngine::handleBreakIgnore(const GdbResultRecord &record, const QVariant &cookie)
 {
+    int index = cookie.toInt();
     // gdb 6.8:
     // ignore 2 0:
     // ~"Will stop next time breakpoint 2 is reached.\n"
@@ -2171,8 +1922,9 @@ void GdbEngine::handleBreakIgnore(const GdbResultRecord &record, int index)
     }
 }
 
-void GdbEngine::handleBreakCondition(const GdbResultRecord &record, int index)
+void GdbEngine::handleBreakCondition(const GdbResultRecord &record, const QVariant &cookie)
 {
+    int index = cookie.toInt();
     BreakHandler *handler = qq->breakHandler();
     if (record.resultClass == GdbResultDone) {
         // we just assume it was successful. otherwise we had to parse
@@ -2196,8 +1948,9 @@ void GdbEngine::handleBreakCondition(const GdbResultRecord &record, int index)
     }
 }
 
-void GdbEngine::handleBreakInsert(const GdbResultRecord &record, int index)
+void GdbEngine::handleBreakInsert(const GdbResultRecord &record, const QVariant &cookie)
 {
+    int index = cookie.toInt();
     BreakHandler *handler = qq->breakHandler();
     if (record.resultClass == GdbResultDone) {
         //qDebug() << "HANDLE BREAK INSERT " << index;
@@ -2219,21 +1972,19 @@ void GdbEngine::handleBreakInsert(const GdbResultRecord &record, int index)
             + data->lineNumber;
         // Should not happen with -break-insert -f. gdb older than 6.8?
         QTC_ASSERT(false, /**/);
-        sendCommand(_("break ") + where, BreakInsert1, index);
 #endif
 #ifdef Q_OS_MAC
         QFileInfo fi(data->fileName);
         QString where = _c('"') + fi.fileName() + _("\":")
             + data->lineNumber;
-        sendCommand(_("break ") + where, BreakInsert1, index);
 #endif
 #ifdef Q_OS_WIN
         QFileInfo fi(data->fileName);
         QString where = _c('"') + fi.fileName() + _("\":")
             + data->lineNumber;
         //QString where = m_data->fileName + _c(':') + data->lineNumber;
-        sendCommand(_("break ") + where, BreakInsert1, index);
 #endif
+        execCommandC(_("break ") + where, handleBreakInsert1, index);
     }
 }
 
@@ -2282,8 +2033,9 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
     }
 }
 
-void GdbEngine::handleBreakInfo(const GdbResultRecord &record, int bpNumber)
+void GdbEngine::handleBreakInfo(const GdbResultRecord &record, const QVariant &cookie)
 {
+    int bpNumber = cookie.toInt();
     BreakHandler *handler = qq->breakHandler();
     if (record.resultClass == GdbResultDone) {
         // Old-style output for multiple breakpoints, presumably in a
@@ -2298,8 +2050,9 @@ void GdbEngine::handleBreakInfo(const GdbResultRecord &record, int bpNumber)
     }
 }
 
-void GdbEngine::handleBreakInsert1(const GdbResultRecord &record, int index)
+void GdbEngine::handleBreakInsert1(const GdbResultRecord &record, const QVariant &cookie)
 {
+    int index = cookie.toInt();
     BreakHandler *handler = qq->breakHandler();
     if (record.resultClass == GdbResultDone) {
         // Pending breakpoints in dylibs on Mac only?
@@ -2329,15 +2082,13 @@ void GdbEngine::attemptBreakpointSynchronization()
     foreach (BreakpointData *data, handler->takeDisabledBreakpoints()) {
         QString bpNumber = data->bpNumber;
         if (!bpNumber.trimmed().isEmpty())
-            sendCommand(_("-break-disable ") + bpNumber, BreakDisable, QVariant(),
-                NeedsStop);
+            sendCommand(_("-break-disable ") + bpNumber, NeedsStop);
     }
 
     foreach (BreakpointData *data, handler->takeEnabledBreakpoints()) {
         QString bpNumber = data->bpNumber;
         if (!bpNumber.trimmed().isEmpty())
-            sendCommand(_("-break-enable ") + bpNumber, BreakEnable, QVariant(),
-                NeedsStop);
+            sendCommand(_("-break-enable ") + bpNumber, NeedsStop);
     }
 
     foreach (BreakpointData *data, handler->takeRemovedBreakpoints()) {
@@ -2345,8 +2096,7 @@ void GdbEngine::attemptBreakpointSynchronization()
         debugMessage(_("DELETING BP %1 IN %2").arg(bpNumber)
             .arg(data->markerFileName));
         if (!bpNumber.trimmed().isEmpty())
-            sendCommand(_("-break-delete ") + bpNumber, BreakDelete, QVariant(),
-                NeedsStop);
+            sendCommand(_("-break-delete ") + bpNumber, NeedsStop);
         delete data;
     }
 
@@ -2356,8 +2106,8 @@ void GdbEngine::attemptBreakpointSynchronization()
         BreakpointData *data = handler->at(index);
         // multiple breakpoints?
         if (data->bpMultiple && data->bpFileName.isEmpty()) {
-            sendCommand(_("info break %1").arg(data->bpNumber),
-                BreakInfo, data->bpNumber.toInt());
+            execCommandC(_("info break %1").arg(data->bpNumber),
+                handleBreakInfo, data->bpNumber.toInt());
             updateNeeded = true;
             break;
         }
@@ -2381,8 +2131,8 @@ void GdbEngine::attemptBreakpointSynchronization()
             // update conditions if needed
             if (data->bpNumber.toInt() && data->condition != data->bpCondition
                    && !data->conditionsMatch()) {
-                sendCommand(_("condition %1 %2").arg(data->bpNumber)
-                    .arg(data->condition), BreakCondition, index);
+                execCommandC(_("condition %1 %2").arg(data->bpNumber).arg(data->condition),
+                              handleBreakCondition, index);
                 //qDebug() << "UPDATE NEEDED BECAUSE OF CONDITION"
                 //    << data->condition << data->bpCondition;
                 updateNeeded = true;
@@ -2390,8 +2140,8 @@ void GdbEngine::attemptBreakpointSynchronization()
             }
             // update ignorecount if needed
             if (data->bpNumber.toInt() && data->ignoreCount != data->bpIgnoreCount) {
-                sendCommand(_("ignore %1 %2").arg(data->bpNumber)
-                    .arg(data->ignoreCount), BreakIgnore, index);
+                execCommandC(_("ignore %1 %2").arg(data->bpNumber).arg(data->ignoreCount),
+                              handleBreakIgnore, index);
                 updateNeeded = true;
                 break;
             }
@@ -2425,12 +2175,13 @@ void GdbEngine::attemptBreakpointSynchronization()
 
 void GdbEngine::reloadDisassembler()
 {
-    emit sendCommand(_("disassemble"), DisassemblerList, m_address);
+    emit execCommandC(_("disassemble"), handleDisassemblerList, m_address);
 }
 
 void GdbEngine::handleDisassemblerList(const GdbResultRecord &record,
-    const QString &cookie)
+    const QVariant &cookie)
 {
+    QString listedLine = cookie.toString();
     QList<DisassemblerLine> lines;
     static const QString pad = _("    ");
     int currentLine = -1;
@@ -2462,7 +2213,7 @@ void GdbEngine::handleDisassemblerList(const GdbResultRecord &record,
                 line.addressDisplay.replace(2, 8, QString());
             line.symbolDisplay = line.symbol + pad;
 
-            if (line.address == cookie)
+            if (line.address == listedLine)
                 currentLine = lines.size();
 
             lines.append(line);
@@ -2534,10 +2285,10 @@ QList<Symbol> GdbEngine::moduleSymbols(const QString &moduleName)
 
 void GdbEngine::reloadModules()
 {
-    sendCommand(_("info shared"), ModulesList, QVariant());
+    execCommand(_("info shared"), handleModulesList);
 }
 
-void GdbEngine::handleModulesList(const GdbResultRecord &record)
+void GdbEngine::handleModulesList(const GdbResultRecord &record, const QVariant &)
 {
     QList<Module> modules;
     if (record.resultClass == GdbResultDone) {
@@ -2586,7 +2337,7 @@ void GdbEngine::handleModulesList(const GdbResultRecord &record)
 
 void GdbEngine::reloadSourceFiles()
 {
-    sendCommand(_("-file-list-exec-source-files"), GdbQuerySources);
+    execCommand(_("-file-list-exec-source-files"), handleQuerySources);
 }
 
 
@@ -2596,17 +2347,17 @@ void GdbEngine::reloadSourceFiles()
 //
 //////////////////////////////////////////////////////////////////////
 
-void GdbEngine::handleStackSelectThread(const GdbResultRecord &record, int)
+void GdbEngine::handleStackSelectThread(const GdbResultRecord &, const QVariant &)
 {
-    Q_UNUSED(record);
     //qDebug("FIXME: StackHandler::handleOutput: SelectThread");
     q->showStatusMessage(tr("Retrieving data for stack view..."), 3000);
     reloadStack();
 }
 
 
-void GdbEngine::handleStackListFrames(const GdbResultRecord &record, bool isFull)
+void GdbEngine::handleStackListFrames(const GdbResultRecord &record, const QVariant &cookie)
 {
+    bool isFull = cookie.toBool();
     QList<StackFrame> stackFrames;
 
     const GdbMi stack = record.data.findChild("stack");
@@ -2683,8 +2434,8 @@ void GdbEngine::selectThread(int index)
     QTC_ASSERT(index < threads.size(), return);
     int id = threads.at(index).id;
     q->showStatusMessage(tr("Retrieving data for stack view..."), 10000);
-    sendCommand(_("-thread-select ") + QString::number(id),
-        StackSelectThread);
+    execCommand(_("-thread-select ") + QString::number(id),
+        handleStackSelectThread);
 }
 
 void GdbEngine::activateFrame(int frameIndex)
@@ -2723,8 +2474,9 @@ void GdbEngine::activateFrame(int frameIndex)
         qDebug() << "FULL NAME NOT USABLE: " << frame.file;
 }
 
-void GdbEngine::handleStackListThreads(const GdbResultRecord &record, int id)
+void GdbEngine::handleStackListThreads(const GdbResultRecord &record, const QVariant &cookie)
 {
+    int id = cookie.toInt();
     // "72^done,{thread-ids={thread-id="2",thread-id="1"},number-of-threads="2"}
     const QList<GdbMi> items = record.data.findChild("thread-ids").children();
     QList<ThreadData> threads;
@@ -2771,10 +2523,11 @@ static inline char registerFormatChar()
 
 void GdbEngine::reloadRegisters()
 {
-    sendCommand(_("-data-list-register-values ") + _c(registerFormatChar()), RegisterListValues);
+    execCommandF(_("-data-list-register-values ") + _c(registerFormatChar()),
+                 handleRegisterListValues, Discardable);
 }
 
-void GdbEngine::handleRegisterListNames(const GdbResultRecord &record)
+void GdbEngine::handleRegisterListNames(const GdbResultRecord &record, const QVariant &)
 {
     if (record.resultClass != GdbResultDone)
         return;
@@ -2786,7 +2539,7 @@ void GdbEngine::handleRegisterListNames(const GdbResultRecord &record)
     qq->registerHandler()->setRegisters(registers);
 }
 
-void GdbEngine::handleRegisterListValues(const GdbResultRecord &record)
+void GdbEngine::handleRegisterListValues(const GdbResultRecord &record, const QVariant &)
 {
     if (record.resultClass != GdbResultDone)
         return;
@@ -3046,7 +2799,7 @@ void GdbEngine::runDirectDebuggingHelper(const WatchData &data, bool dumpChildre
 
     QVariant var;
     var.setValue(data);
-    sendSynchronizedCommand(cmd, WatchDebuggingHelperValue3, var);
+    execCommandFC(cmd, handleDebuggingHelperValue3, WatchUpdate, var);
 
     q->showStatusMessage(
         tr("Retrieving data for watch view (%1 requests pending)...")
@@ -3088,25 +2841,25 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
 
     QVariant var;
     var.setValue(data);
-    sendSynchronizedCommand(cmd, WatchDebuggingHelperValue1, var);
+    execCommandFC(cmd, handleDebuggingHelperValue1, WatchUpdate, var);
 
     q->showStatusMessage(
         tr("Retrieving data for watch view (%1 requests pending)...")
             .arg(m_pendingRequests + 1), 10000);
 
     // retrieve response
-    sendSynchronizedCommand(_("p (char*)&qDumpOutBuffer"), WatchDebuggingHelperValue2, var);
+    execCommandFC(_("p (char*)&qDumpOutBuffer"), handleDebuggingHelperValue2, WatchUpdate, var);
 }
 
 void GdbEngine::createGdbVariable(const WatchData &data)
 {
-    sendSynchronizedCommand(_("-var-delete \"") + data.iname + _c('"'));
+    sendCommand(_("-var-delete \"") + data.iname + _c('"'), WatchUpdate);
     QString exp = data.exp;
     if (exp.isEmpty() && data.addr.startsWith(__("0x")))
         exp = _("*(") + gdbQuoteTypes(data.type) + _("*)") + data.addr;
     QVariant val = QVariant::fromValue<WatchData>(data);
-    sendSynchronizedCommand(_("-var-create \"") + data.iname + _("\" * \"")
-        + exp + _c('"'), WatchVarCreate, val);
+    execCommandFC(_("-var-create \"") + data.iname + _("\" * \"")
+        + exp + _c('"'), handleVarCreate, WatchUpdate, val);
 }
 
 void GdbEngine::updateSubItem(const WatchData &data0)
@@ -3200,7 +2953,7 @@ void GdbEngine::updateSubItem(const WatchData &data0)
         qDebug() << "UPDATE SUBITEM: VALUE";
         #endif
         QString cmd = _("-var-evaluate-expression \"") + data.iname + _c('"');
-        sendSynchronizedCommand(cmd, WatchEvaluateExpression,
+        execCommandFC(cmd, handleEvaluateExpression, WatchUpdate,
             QVariant::fromValue(data));
         return;
     }
@@ -3226,7 +2979,7 @@ void GdbEngine::updateSubItem(const WatchData &data0)
     if (data.isChildrenNeeded()) {
         QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
         QString cmd = _("-var-list-children --all-values \"") + data.variable + _c('"');
-        sendSynchronizedCommand(cmd, WatchVarListChildren, QVariant::fromValue(data));
+        execCommandFC(cmd, handleVarListChildren, WatchUpdate, QVariant::fromValue(data));
         return;
     }
 
@@ -3251,7 +3004,7 @@ void GdbEngine::updateSubItem(const WatchData &data0)
     if (data.isChildCountNeeded()) {
         QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
         QString cmd = _("-var-list-children --all-values \"") + data.variable + _c('"');
-        sendCommand(cmd, WatchVarListChildren, QVariant::fromValue(data));
+        execCommandFC(cmd, handleVarListChildren, Discardable, QVariant::fromValue(data));
         return;
     }
 
@@ -3315,7 +3068,7 @@ void GdbEngine::updateWatchModel2()
     }
 }
 
-void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record)
+void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const QVariant &)
 {
     m_dumperHelper.clear();
     //qDebug() << "DATA DUMPER TRIAL:" << record.toString();
@@ -3388,7 +3141,7 @@ void GdbEngine::sendWatchParameters(const QByteArray &params0)
     sendCommand(_(encoded));
 }
 
-void GdbEngine::handleVarAssign()
+void GdbEngine::handleVarAssign(const GdbResultRecord &, const QVariant &)
 {
     // everything might have changed, force re-evaluation
     // FIXME: Speed this up by re-using variables and only
@@ -3410,9 +3163,9 @@ void GdbEngine::setWatchDataType(WatchData &data, const GdbMi &mi)
 }
 
 void GdbEngine::handleVarCreate(const GdbResultRecord &record,
-    const WatchData &data0)
+    const QVariant &cookie)
 {
-    WatchData data = data0;
+    WatchData data = cookie.value<WatchData>();
     // happens e.g. when we already issued a var-evaluate command
     if (!data.isValid())
         return;
@@ -3451,9 +3204,9 @@ void GdbEngine::handleVarCreate(const GdbResultRecord &record,
 }
 
 void GdbEngine::handleEvaluateExpression(const GdbResultRecord &record,
-    const WatchData &data0)
+    const QVariant &cookie)
 {
-    WatchData data = data0;
+    WatchData data = cookie.value<WatchData>();
     QTC_ASSERT(data.isValid(), qDebug() << "HUH?");
     if (record.resultClass == GdbResultDone) {
         //if (col == 0)
@@ -3468,7 +3221,7 @@ void GdbEngine::handleEvaluateExpression(const GdbResultRecord &record,
     //updateWatchModel2();
 }
 
-void GdbEngine::handleDebuggingHelperSetup(const GdbResultRecord &record)
+void GdbEngine::handleDebuggingHelperSetup(const GdbResultRecord &record, const QVariant &)
 {
     //qDebug() << "CUSTOM SETUP RESULT: " << record.toString();
     if (record.resultClass == GdbResultDone) {
@@ -3480,9 +3233,9 @@ void GdbEngine::handleDebuggingHelperSetup(const GdbResultRecord &record)
 }
 
 void GdbEngine::handleDebuggingHelperValue1(const GdbResultRecord &record,
-    const WatchData &data0)
+    const QVariant &cookie)
 {
-    WatchData data = data0;
+    WatchData data = cookie.value<WatchData>();
     QTC_ASSERT(data.isValid(), return);
     if (record.resultClass == GdbResultDone) {
         // ignore this case, data will follow
@@ -3498,7 +3251,7 @@ void GdbEngine::handleDebuggingHelperValue1(const GdbResultRecord &record,
                 && msg.startsWith(__("The program being debugged stopped while"))
                 && msg.contains(__("qDumpObjectData440"))) {
             // Fake full stop
-            sendCommand(_("p 0"), GdbAsyncOutput2);  // dummy
+            execCommand(_("p 0"), handleAsyncOutput2);  // dummy
             return;
         }
 #endif
@@ -3512,9 +3265,9 @@ void GdbEngine::handleDebuggingHelperValue1(const GdbResultRecord &record,
 }
 
 void GdbEngine::handleDebuggingHelperValue2(const GdbResultRecord &record,
-    const WatchData &data0)
+    const QVariant &cookie)
 {
-    WatchData data = data0;
+    WatchData data = cookie.value<WatchData>();
     QTC_ASSERT(data.isValid(), return);
     //qDebug() << "CUSTOM VALUE RESULT: " << record.toString();
     //qDebug() << "FOR DATA: " << data.toString() << record.resultClass;
@@ -3611,9 +3364,9 @@ void GdbEngine::handleDebuggingHelperValue2(const GdbResultRecord &record,
 }
 
 void GdbEngine::handleDebuggingHelperValue3(const GdbResultRecord &record,
-    const WatchData &data0)
+    const QVariant &cookie)
 {
-    WatchData data = data0;
+    WatchData data = cookie.value<WatchData>();
     QByteArray out = record.data.findChild("consolestreamoutput").data();
     while (out.endsWith(' ') || out.endsWith('\n'))
         out.chop(1);
@@ -3653,7 +3406,7 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResultRecord &record,
             QString cmd = _("qdumpqstring (") + data1.exp + _c(')');
             QVariant var;
             var.setValue(data1);
-            sendSynchronizedCommand(cmd, WatchDebuggingHelperValue3, var);
+            execCommandFC(cmd, handleDebuggingHelperValue3, WatchUpdate, var);
         }
     } else {
         //: Value for variable
@@ -3675,12 +3428,12 @@ void GdbEngine::updateLocals()
     QString level = QString::number(currentFrame());
     // '2' is 'list with type and value'
     QString cmd = _("-stack-list-arguments 2 ") + level + _c(' ') + level;
-    sendSynchronizedCommand(cmd, StackListArguments);                 // stage 1/2
+    execCommandF(cmd, handleStackListArguments, WatchUpdate);                 // stage 1/2
     // '2' is 'list with type and value'
-    sendSynchronizedCommand(_("-stack-list-locals 2"), StackListLocals); // stage 2/2
+    execCommandF(_("-stack-list-locals 2"), handleStackListLocals, WatchUpdate); // stage 2/2
 }
 
-void GdbEngine::handleStackListArguments(const GdbResultRecord &record)
+void GdbEngine::handleStackListArguments(const GdbResultRecord &record, const QVariant &)
 {
     // stage 1/2
 
@@ -3714,7 +3467,7 @@ void GdbEngine::handleStackListArguments(const GdbResultRecord &record)
     }
 }
 
-void GdbEngine::handleStackListLocals(const GdbResultRecord &record)
+void GdbEngine::handleStackListLocals(const GdbResultRecord &record, const QVariant &)
 {
     // stage 2/2
 
@@ -3856,7 +3609,7 @@ void GdbEngine::handleVarListChildrenHelper(const GdbMi &item,
         //qDebug() << "DATA" << data.toString();
         QString cmd = _("-var-list-children --all-values \"") + data.variable + _c('"');
         //iname += '.' + exp;
-        sendSynchronizedCommand(cmd, WatchVarListChildren, QVariant::fromValue(data));
+        execCommandFC(cmd, handleVarListChildren, WatchUpdate, QVariant::fromValue(data));
     } else if (item.findChild("numchild").data() == "0") {
         // happens for structs without data, e.g. interfaces.
         WatchData data;
@@ -3874,7 +3627,7 @@ void GdbEngine::handleVarListChildrenHelper(const GdbMi &item,
         WatchData data;
         data.iname = _(name);
         QString cmd = _("-var-list-children --all-values \"") + data.variable + _c('"');
-        sendSynchronizedCommand(cmd, WatchVarListChildren, QVariant::fromValue(data));
+        execCommandFC(cmd, handleVarListChildren, WatchUpdate, QVariant::fromValue(data));
     } else if (exp == "staticMetaObject") {
         //    && item.findChild("type").data() == "const QMetaObject")
         // FIXME: Namespaces?
@@ -3937,10 +3690,10 @@ void GdbEngine::handleVarListChildrenHelper(const GdbMi &item,
 }
 
 void GdbEngine::handleVarListChildren(const GdbResultRecord &record,
-    const WatchData &data0)
+    const QVariant &cookie)
 {
     //WatchResultCounter dummy(this, WatchVarListChildren);
-    WatchData data = data0;
+    WatchData data = cookie.value<WatchData>();
     if (!data.isValid())
         return;
     if (record.resultClass == GdbResultDone) {
@@ -3977,13 +3730,14 @@ void GdbEngine::handleVarListChildren(const GdbResultRecord &record,
 }
 
 void GdbEngine::handleToolTip(const GdbResultRecord &record,
-        const QByteArray &what)
+        const QVariant &cookie)
 {
+    const QByteArray &what = cookie.toByteArray();
     //qDebug() << "HANDLE TOOLTIP: " << what << m_toolTip.toString();
     //    << "record: " << record.toString();
     if (record.resultClass == GdbResultError) {
         if (what == "create") {
-            sendCommand(_("ptype ") + m_toolTip.exp, WatchToolTip, QByteArray("ptype"));
+            execCommandFC(_("ptype ") + m_toolTip.exp, handleToolTip, Discardable, QByteArray("ptype"));
             return;
         }
         if (what == "evaluate") {
@@ -4001,8 +3755,8 @@ void GdbEngine::handleToolTip(const GdbResultRecord &record,
                 runDebuggingHelper(m_toolTip, false);
             else
                 q->showStatusMessage(tr("Retrieving data for tooltip..."), 10000);
-                sendCommand(_("-data-evaluate-expression ") + m_toolTip.exp,
-                    WatchToolTip, QByteArray("evaluate"));
+                execCommandFC(_("-data-evaluate-expression ") + m_toolTip.exp,
+                    handleToolTip, Discardable, QByteArray("evaluate"));
                 //sendToolTipCommand(_("-var-evaluate-expression tooltip"))
             return;
         }
@@ -4043,7 +3797,7 @@ void GdbEngine::assignValueInDebugger(const QString &expression, const QString &
 {
     sendCommand(_("-var-delete assign"));
     sendCommand(_("-var-create assign * ") + expression);
-    sendCommand(_("-var-assign assign ") + value, WatchVarAssign);
+    execCommandF(_("-var-assign assign ") + value, handleVarAssign, Discardable);
 }
 
 void GdbEngine::tryLoadDebuggingHelpers()
@@ -4071,14 +3825,14 @@ void GdbEngine::tryLoadDebuggingHelpers()
     sendCommand(_("sharedlibrary .*")); // for LoadLibraryA
     //sendCommand(_("handle SIGSEGV pass stop print"));
     //sendCommand(_("set unwindonsignal off"));
-    sendCommand(_("call LoadLibraryA(\"") + lib + _("\")"),
-        WatchDebuggingHelperSetup);
+    execCommand(_("call LoadLibraryA(\"") + lib + _("\")"),
+        handleWatchDebuggingHelperSetup);
     sendCommand(_("sharedlibrary ") + dotEscape(lib));
 #elif defined(Q_OS_MAC)
     //sendCommand(_("sharedlibrary libc")); // for malloc
     //sendCommand(_("sharedlibrary libdl")); // for dlopen
-    sendCommand(_("call (void)dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
-        WatchDebuggingHelperSetup);
+    execCommand(_("call (void)dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
+        handleWatchDebuggingHelperSetup);
     //sendCommand(_("sharedlibrary ") + dotEscape(lib));
     m_debuggingHelperState = DebuggingHelperLoadTried;
 #else
@@ -4086,23 +3840,23 @@ void GdbEngine::tryLoadDebuggingHelpers()
     QString flag = QString::number(RTLD_NOW);
     sendCommand(_("sharedlibrary libc")); // for malloc
     sendCommand(_("sharedlibrary libdl")); // for dlopen
-    sendCommand(_("call (void*)dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
-        WatchDebuggingHelperSetup);
+    execCommand(_("call (void*)dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
+        handleDebuggingHelperSetup);
     // some older systems like CentOS 4.6 prefer this:
-    sendCommand(_("call (void*)__dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
-        WatchDebuggingHelperSetup);
+    execCommand(_("call (void*)__dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
+        handleDebuggingHelperSetup);
     sendCommand(_("sharedlibrary ") + dotEscape(lib));
 #endif
     // retreive list of dumpable classes
     sendCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"));
-    sendCommand(_("p (char*)&qDumpOutBuffer"), GdbQueryDebuggingHelper);
+    execCommand(_("p (char*)&qDumpOutBuffer"), handleQueryDebuggingHelper);
 }
 
 void GdbEngine::recheckDebuggingHelperAvailability()
 {
     // retreive list of dumpable classes
     sendCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"));
-    sendCommand(_("p (char*)&qDumpOutBuffer"), GdbQueryDebuggingHelper);
+    execCommand(_("p (char*)&qDumpOutBuffer"), handleQueryDebuggingHelper);
 }
 
 IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h
index 7b07f5bc1833a2c9c79288ec91f813a28718b436..6c3df5dd2fc6ac40c4705fa6173397308f9e8cce 100644
--- a/src/plugins/debugger/gdbengine.h
+++ b/src/plugins/debugger/gdbengine.h
@@ -63,16 +63,6 @@ class GdbMi;
 class WatchData;
 class BreakpointData;
 
-struct GdbCookie
-{
-    GdbCookie() : type(0), synchronized(false) {}
-
-    QString command;
-    int type;
-    bool synchronized;
-    QVariant cookie;
-};
-
 enum DebuggingHelperState
 {
     DebuggingHelperUninitialized,
@@ -154,19 +144,47 @@ private:
 
     void handleResult(const GdbResultRecord &, int type, const QVariant &);
 
+public: // otherwise the Qt flag macros are unhappy
+    enum GdbCommandFlag {
+        NoFlags = 0,
+        NeedsStop = 1,
+        Discardable = 2,
+        RebuildModel = 4,
+        WatchUpdate = Discardable|RebuildModel
+    };
+    Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
+private:
+
+    typedef void (GdbEngine::*GdbCommandCallback)(const GdbResultRecord &record, const QVariant &cookie);
+
+    struct GdbCommand
+    {
+        GdbCommand() : flags(0), callback(0), callbackName(0) {}
+
+        int flags;
+        GdbCommandCallback callback;
+        const char *callbackName;
+        QString command;
+        QVariant cookie;
+    };
+
     // type and cookie are sender-internal data, opaque for the "event
     // queue". resultNeeded == true increments m_pendingResults on
     // send and decrements on receipt, effectively preventing 
     // watch model updates before everything is finished.
-    enum StopNeeded { DoesNotNeedStop, NeedsStop };
-    enum Synchronization { NotSynchronized, Synchronized };
-    void sendCommand(const QString &command,
-        int type = 0, const QVariant &cookie = QVariant(),
-        StopNeeded needStop = DoesNotNeedStop,
-        Synchronization synchronized = NotSynchronized);
-    void sendSynchronizedCommand(const QString & command,
-        int type = 0, const QVariant &cookie = QVariant(),
-        StopNeeded needStop = DoesNotNeedStop);
+    void flushCommand(GdbCommand &cmd);
+    void execCommandInternal(const QString &command, GdbCommandFlags flags,
+                             GdbCommandCallback callback, const char *callbackName,
+                             const QVariant &cookie);
+    #define execCommand(command,callback) \
+        execCommandInternal(command, NoFlags, &GdbEngine::callback, STRINGIFY(callback), QVariant())
+    #define execCommandF(command,callback,flags) \
+        execCommandInternal(command, flags, &GdbEngine::callback, STRINGIFY(callback), QVariant())
+    #define execCommandC(command,callback,cookie) \
+        execCommandInternal(command, NoFlags, &GdbEngine::callback, STRINGIFY(callback), cookie)
+    #define execCommandFC(command,callback,flags,cookie) \
+        execCommandInternal(command, flags, &GdbEngine::callback, STRINGIFY(callback), cookie)
+    void sendCommand(const QString &command, GdbCommandFlags flags = NoFlags);
 
     void setTokenBarrier();
 
@@ -183,25 +201,27 @@ private slots:
 private:
     int terminationIndex(const QByteArray &buffer, int &length);
     void handleResponse(const QByteArray &buff);
-    void handleStart(const GdbResultRecord &response);
-    void handleAttach();
-    void handleStubAttached();
+    void handleStart(const GdbResultRecord &response, const QVariant &);
+    void handleAttach(const GdbResultRecord &, const QVariant &);
+    void handleStubAttached(const GdbResultRecord &, const QVariant &);
     void handleAqcuiredInferior();
+    void handleAsyncOutput2(const GdbResultRecord &, const QVariant &cookie);
     void handleAsyncOutput2(const GdbMi &data);
     void handleAsyncOutput(const GdbMi &data);
     void handleResultRecord(const GdbResultRecord &response);
-    void handleFileExecAndSymbols(const GdbResultRecord &response);
-    void handleExecRun(const GdbResultRecord &response);
-    void handleExecJumpToLine(const GdbResultRecord &response);
-    void handleExecRunToFunction(const GdbResultRecord &response);
-    void handleInfoShared(const GdbResultRecord &response);
-    void handleInfoProc(const GdbResultRecord &response);
-    void handleInfoThreads(const GdbResultRecord &response);
-    void handleShowVersion(const GdbResultRecord &response);
-    void handleQueryPwd(const GdbResultRecord &response);
-    void handleQuerySources(const GdbResultRecord &response);
-    void handleTargetCore(const GdbResultRecord &response);
-    void handleExit(const GdbResultRecord &response);
+    void handleAutoContinue(const GdbResultRecord &, const QVariant &);
+    void handleFileExecAndSymbols(const GdbResultRecord &response, const QVariant &);
+    void handleExecRun(const GdbResultRecord &response, const QVariant &);
+    void handleExecJumpToLine(const GdbResultRecord &response, const QVariant &);
+    void handleExecRunToFunction(const GdbResultRecord &response, const QVariant &);
+    void handleInfoShared(const GdbResultRecord &response, const QVariant &);
+    void handleInfoProc(const GdbResultRecord &response, const QVariant &);
+    void handleInfoThreads(const GdbResultRecord &response, const QVariant &);
+    void handleShowVersion(const GdbResultRecord &response, const QVariant &);
+    void handleQueryPwd(const GdbResultRecord &response, const QVariant &);
+    void handleQuerySources(const GdbResultRecord &response, const QVariant &);
+    void handleTargetCore(const GdbResultRecord &, const QVariant &);
+    void handleExit(const GdbResultRecord &, const QVariant &);
     void debugMessage(const QString &msg);
 
     OutputCollector m_outputCollector;
@@ -214,7 +234,7 @@ private:
 
     Core::Utils::ConsoleProcess m_stubProc;
 
-    QHash<int, GdbCookie> m_cookieForToken;
+    QHash<int, GdbCommand> m_cookieForToken;
     QHash<int, QByteArray> m_customOutputForToken;
 
     QByteArray m_pendingConsoleStreamOutput;
@@ -237,13 +257,13 @@ private:
     //
     // Breakpoint specific stuff
     //
-    void handleBreakList(const GdbResultRecord &record);
+    void handleBreakList(const GdbResultRecord &record, const QVariant &);
     void handleBreakList(const GdbMi &table);
-    void handleBreakIgnore(const GdbResultRecord &record, int index);
-    void handleBreakInsert(const GdbResultRecord &record, int index);
-    void handleBreakInsert1(const GdbResultRecord &record, int index);
-    void handleBreakCondition(const GdbResultRecord &record, int index);
-    void handleBreakInfo(const GdbResultRecord &record, int index);
+    void handleBreakIgnore(const GdbResultRecord &record, const QVariant &cookie);
+    void handleBreakInsert(const GdbResultRecord &record, const QVariant &cookie);
+    void handleBreakInsert1(const GdbResultRecord &record, const QVariant &cookie);
+    void handleBreakCondition(const GdbResultRecord &record, const QVariant &cookie);
+    void handleBreakInfo(const GdbResultRecord &record, const QVariant &cookie);
     void extractDataFromInfoBreak(const QString &output, BreakpointData *data);
     void breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt);
     void sendInsertBreakpoint(int index);
@@ -253,7 +273,7 @@ private:
     // Disassembler specific stuff
     //
     void handleDisassemblerList(const GdbResultRecord &record,
-        const QString &cookie);
+        const QVariant &cookie);
     void reloadDisassembler();
     QString m_address;
 
@@ -262,15 +282,15 @@ private:
     // Modules specific stuff
     //
     void reloadModules();
-    void handleModulesList(const GdbResultRecord &record);
+    void handleModulesList(const GdbResultRecord &record, const QVariant &);
 
 
     //
     // Register specific stuff
     // 
     Q_SLOT void reloadRegisters();
-    void handleRegisterListNames(const GdbResultRecord &record);
-    void handleRegisterListValues(const GdbResultRecord &record);
+    void handleRegisterListNames(const GdbResultRecord &record, const QVariant &);
+    void handleRegisterListValues(const GdbResultRecord &record, const QVariant &);
 
     //
     // Source file specific stuff
@@ -280,9 +300,9 @@ private:
     //
     // Stack specific stuff
     // 
-    void handleStackListFrames(const GdbResultRecord &record, bool isFull);
-    void handleStackSelectThread(const GdbResultRecord &record, int cookie);
-    void handleStackListThreads(const GdbResultRecord &record, int cookie);
+    void handleStackListFrames(const GdbResultRecord &record, const QVariant &cookie);
+    void handleStackSelectThread(const GdbResultRecord &, const QVariant &);
+    void handleStackListThreads(const GdbResultRecord &record, const QVariant &cookie);
     Q_SLOT void reloadStack();
     Q_SLOT void reloadFullStack();
 
@@ -316,25 +336,25 @@ private:
     bool hasDebuggingHelperForType(const QString &type) const;
 
     void handleVarListChildren(const GdbResultRecord &record,
-        const WatchData &cookie);
+        const QVariant &cookie);
     void handleVarCreate(const GdbResultRecord &record,
-        const WatchData &cookie);
-    void handleVarAssign();
+        const QVariant &cookie);
+    void handleVarAssign(const GdbResultRecord &, const QVariant &);
     void handleEvaluateExpression(const GdbResultRecord &record,
-        const WatchData &cookie);
+        const QVariant &cookie);
     void handleToolTip(const GdbResultRecord &record,
-        const QByteArray &cookie);
-    void handleQueryDebuggingHelper(const GdbResultRecord &record);
+        const QVariant &cookie);
+    void handleQueryDebuggingHelper(const GdbResultRecord &record, const QVariant &);
     void handleDebuggingHelperValue1(const GdbResultRecord &record,
-        const WatchData &cookie);
+        const QVariant &cookie);
     void handleDebuggingHelperValue2(const GdbResultRecord &record,
-        const WatchData &cookie);
+        const QVariant &cookie);
     void handleDebuggingHelperValue3(const GdbResultRecord &record,
-        const WatchData &cookie);
+        const QVariant &cookie);
     void handleDebuggingHelperEditValue(const GdbResultRecord &record);
-    void handleDebuggingHelperSetup(const GdbResultRecord &record);
-    void handleStackListLocals(const GdbResultRecord &record);
-    void handleStackListArguments(const GdbResultRecord &record);
+    void handleDebuggingHelperSetup(const GdbResultRecord &record, const QVariant &);
+    void handleStackListLocals(const GdbResultRecord &record, const QVariant &);
+    void handleStackListArguments(const GdbResultRecord &record, const QVariant &);
     void handleVarListChildrenHelper(const GdbMi &child,
         const WatchData &parent);
     void setWatchDataType(WatchData &data, const GdbMi &mi);
@@ -354,7 +374,7 @@ private:
     bool m_waitingForFirstBreakpointToBeHit;
     bool m_modulesListOutdated;
 
-    QList<GdbCookie> m_commandsToRunOnTemporaryBreak;
+    QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
 
     DebuggerManager *q;
     IDebuggerManagerAccessForEngines *qq;
@@ -363,4 +383,6 @@ private:
 } // namespace Internal
 } // namespace Debugger
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(Debugger::Internal::GdbEngine::GdbCommandFlags)
+
 #endif // DEBUGGER_GDBENGINE_H