Commit 063d13e0 authored by hjk's avatar hjk
Browse files

debugger: work on general shutdown handling

parent 6b510cb4
......@@ -82,6 +82,16 @@
#include <QtGui/QToolButton>
#include <QtGui/QToolTip>
#define DEBUG_STATE 1
#ifdef DEBUG_STATE
// use Q_FUNC_INFO?
# define STATE_DEBUG(s) \
{ QString msg; QTextStream ts(&msg); ts << s; \
showDebuggerOutput(LogDebug, msg); }
#else
# define STATE_DEBUG(s)
#endif
namespace Debugger {
namespace Internal {
......@@ -458,8 +468,7 @@ QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTy
}
m_engine = 0;
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << gdbEngine << winEngine << scriptEngine << rc.size();
STATE_DEBUG(gdbEngine << winEngine << scriptEngine << rc.size());
return rc;
}
......@@ -526,8 +535,6 @@ void DebuggerManager::clearStatusMessage()
void DebuggerManager::showStatusMessage(const QString &msg, int timeout)
{
Q_UNUSED(timeout)
if (Debugger::Constants::Internal::debug)
qDebug() << "STATUS MSG: " << msg;
showDebuggerOutput(LogStatus, msg);
m_statusLabel->setText(QLatin1String(" ") + msg);
if (timeout > 0) {
......@@ -572,8 +579,7 @@ void DebuggerManager::notifyInferiorExited()
void DebuggerManager::notifyInferiorPidChanged(qint64 pid)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << m_inferiorPid << pid;
STATE_DEBUG(m_inferiorPid << pid);
if (m_inferiorPid != pid) {
m_inferiorPid = pid;
......@@ -588,9 +594,7 @@ void DebuggerManager::showApplicationOutput(const QString &str)
void DebuggerManager::shutdown()
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << m_engine;
STATE_DEBUG(m_engine);
if (m_engine)
m_engine->shutdown();
m_engine = 0;
......@@ -643,9 +647,7 @@ void DebuggerManager::toggleBreakpoint()
void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
STATE_DEBUG(fileName << lineNumber);
QTC_ASSERT(m_breakHandler, return);
if (status() != DebuggerInferiorRunning
&& status() != DebuggerInferiorStopped
......@@ -666,9 +668,7 @@ void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
void DebuggerManager::toggleBreakpointEnabled(const QString &fileName, int lineNumber)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
STATE_DEBUG(fileName << lineNumber);
QTC_ASSERT(m_breakHandler, return);
if (status() != DebuggerInferiorRunning
&& status() != DebuggerInferiorStopped
......@@ -726,8 +726,6 @@ static IDebuggerEngine *debuggerEngineForToolChain(ProjectExplorer::ToolChain::T
default:
break;
}
if (Debugger::Constants::Internal::debug)
qDebug() << "Toolchain" << tc << rc;
return rc;
}
......@@ -819,9 +817,6 @@ static IDebuggerEngine *determineDebuggerEngine(int /* pid */,
void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
{
m_startParameters = sp;
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << '\n' << *m_startParameters;
m_inferiorPid = m_startParameters->attachPID > 0
? m_startParameters->attachPID : 0;
const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChain::ToolChainType>(m_startParameters->toolChainType));
......@@ -849,7 +844,7 @@ void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
}
if (!m_engine) {
debuggingFinished();
emit debuggingFinished();
// Create Message box with possibility to go to settings
QAbstractButton *settingsButton = 0;
QMessageBox msgBox(QMessageBox::Warning, tr("Warning"),
......@@ -865,9 +860,7 @@ void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
return;
}
if (Debugger::Constants::Internal::debug)
qDebug() << m_startParameters->executable << m_engine;
STATE_DEBUG(m_startParameters->executable << m_engine);
setBusyCursor(false);
setStatus(DebuggerProcessStartingUp);
connect(m_engine, SIGNAL(startFailed()), this, SLOT(startFailed()));
......@@ -878,7 +871,7 @@ void DebuggerManager::startFailed()
{
disconnect(m_engine, SIGNAL(startFailed()), this, SLOT(startFailed()));
setStatus(DebuggerProcessNotReady);
debuggingFinished();
emit debuggingFinished();
}
void DebuggerManager::cleanupViews()
......@@ -895,9 +888,7 @@ void DebuggerManager::cleanupViews()
void DebuggerManager::exitDebugger()
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO;
STATE_DEBUG("");
if (m_engine)
m_engine->exitDebugger();
cleanupViews();
......@@ -906,6 +897,14 @@ void DebuggerManager::exitDebugger()
emit debuggingFinished();
}
void DebuggerManager::notifyEngineFinished()
{
cleanupViews();
setStatus(DebuggerProcessNotReady);
setBusyCursor(false);
emit debuggingFinished();
}
DebuggerStartParametersPtr DebuggerManager::startParameters() const
{
return m_startParameters;
......@@ -1004,9 +1003,7 @@ void DebuggerManager::executeDebuggerCommand()
void DebuggerManager::executeDebuggerCommand(const QString &command)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO <<command;
STATE_DEBUG(command);
QTC_ASSERT(m_engine, return);
m_engine->executeDebuggerCommand(command);
}
......@@ -1074,9 +1071,7 @@ void DebuggerManager::addToWatchWindow()
void DebuggerManager::setBreakpoint(const QString &fileName, int lineNumber)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
STATE_DEBUG(Q_FUNC_INFO << fileName << lineNumber);
QTC_ASSERT(m_breakHandler, return);
m_breakHandler->setBreakpoint(fileName, lineNumber);
attemptBreakpointSynchronization();
......@@ -1114,14 +1109,13 @@ static bool isAllowedTransition(int from, int to)
void DebuggerManager::setStatus(int status)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << "STATUS CHANGE: from" << stateName(m_status)
<< "to" << stateName(status);
STATE_DEBUG("STATUS CHANGE: FROM " << stateName(m_status)
<< " TO " << stateName(status));
if (status == m_status)
return;
if (1 && !isAllowedTransition(m_status, status)) {
if (!isAllowedTransition(m_status, status)) {
const QString msg = QString::fromLatin1("%1: UNEXPECTED TRANSITION: %2 -> %3")
.arg(_(Q_FUNC_INFO), _(stateName(m_status)), _(stateName(status)));
qWarning("%s", qPrintable(msg));
......@@ -1138,6 +1132,10 @@ void DebuggerManager::setStatus(int status)
const bool ready = status == DebuggerInferiorStopped
&& m_startParameters->startMode != AttachCore;
STATE_DEBUG("STARTED: " << started << " RUNNING: " << running
<< " READY: " << ready);
if (ready)
QApplication::alert(mainWindow(), 3000);
......@@ -1171,7 +1169,7 @@ void DebuggerManager::setStatus(int status)
void DebuggerManager::setBusyCursor(bool busy)
{
//qDebug() << "BUSY FROM: " << m_busy << " TO: " << m_busy;
//STATE_DEBUG("BUSY FROM: " << m_busy << " TO: " << m_busy);
if (busy == m_busy)
return;
m_busy = busy;
......@@ -1209,8 +1207,7 @@ void DebuggerManager::detachDebugger()
void DebuggerManager::interruptDebuggingRequest()
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << status();
STATE_DEBUG(status());
if (!m_engine)
return;
bool interruptIsExit = (status() != DebuggerInferiorRunning);
......@@ -1228,8 +1225,7 @@ void DebuggerManager::runToLineExec()
int lineNumber = -1;
emit currentTextEditorRequested(&fileName, &lineNumber, 0);
if (m_engine && !fileName.isEmpty()) {
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
STATE_DEBUG(fileName << lineNumber);
m_engine->runToLineExec(fileName, lineNumber);
}
}
......@@ -1261,8 +1257,7 @@ void DebuggerManager::runToFunctionExec()
}
}
}
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << functionName;
STATE_DEBUG(functionName);
if (m_engine && !functionName.isEmpty())
m_engine->runToFunctionExec(functionName);
......@@ -1274,8 +1269,7 @@ void DebuggerManager::jumpToLineExec()
int lineNumber = -1;
emit currentTextEditorRequested(&fileName, &lineNumber, 0);
if (m_engine && !fileName.isEmpty()) {
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
STATE_DEBUG(fileName << lineNumber);
m_engine->jumpToLineExec(fileName, lineNumber);
}
}
......@@ -1412,8 +1406,10 @@ QString DebuggerManager::qtDumperLibraryName() const
QStringList DebuggerManager::qtDumperLibraryLocations() const
{
if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) {
const QString customLocation = theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
const QString location = tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
const QString customLocation =
theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
const QString location =
tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
return QStringList(location);
}
return m_startParameters->dumperLibraryLocations;
......@@ -1422,9 +1418,12 @@ QStringList DebuggerManager::qtDumperLibraryLocations() const
void DebuggerManager::showQtDumperLibraryWarning(const QString &details)
{
QMessageBox dialog(mainWindow());
QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"), QMessageBox::ActionRole);
QPushButton *helperOff = dialog.addButton(tr("Turn helper usage off"), QMessageBox::ActionRole);
QPushButton *justContinue = dialog.addButton(tr("Continue anyway"), QMessageBox::AcceptRole);
QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"),
QMessageBox::ActionRole);
QPushButton *helperOff = dialog.addButton(tr("Turn helper usage off"),
QMessageBox::ActionRole);
QPushButton *justContinue = dialog.addButton(tr("Continue anyway"),
QMessageBox::AcceptRole);
dialog.setDefaultButton(justContinue);
dialog.setWindowTitle(tr("Debugging helper missing"));
dialog.setText(tr("The debugger did not find the debugging helper library."));
......
......@@ -227,6 +227,7 @@ private:
virtual void notifyInferiorRunning() = 0;
virtual void notifyInferiorExited() = 0;
virtual void notifyInferiorPidChanged(qint64) = 0;
virtual void notifyEngineFinished() {} // FIXME: make pure
virtual ModulesHandler *modulesHandler() = 0;
virtual BreakHandler *breakHandler() = 0;
......@@ -374,6 +375,7 @@ private:
void notifyInferiorRunning();
void notifyInferiorExited();
void notifyInferiorPidChanged(qint64);
void notifyEngineFinished();
void cleanupViews();
......@@ -395,9 +397,6 @@ public:
// stuff in this block should be made private by moving it to
// one of the interfaces
int status() const { return m_status; }
// FIXME: hide this in the engines?
//DebuggerStartMode startMode() const;
QList<Symbol> moduleSymbols(const QString &moduleName);
signals:
......
......@@ -453,19 +453,19 @@ void DebuggerPlugin::shutdown()
m_manager = 0;
}
static inline QString msgParameterMissing(const QString &a)
static QString msgParameterMissing(const QString &a)
{
return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
}
static inline QString msgInvalidNumericParameter(const QString &a, const QString &number)
static QString msgInvalidNumericParameter(const QString &a, const QString &number)
{
return DebuggerPlugin::tr("The parameter '%1' of option '%2' is not a number.").arg(number, a);
}
// Parse arguments
bool DebuggerPlugin::parseArgument(QStringList::const_iterator &it,
const QStringList::const_iterator& cend,
const QStringList::const_iterator &cend,
QString *errorMessage)
{
const QString &option = *it;
......@@ -529,7 +529,9 @@ bool DebuggerPlugin::parseArguments(const QStringList &args, QString *errorMessa
if (!parseArgument(it, cend, errorMessage))
return false;
if (Debugger::Constants::Internal::debug)
qDebug().nospace() << args << "engines=0x" << QString::number(m_cmdLineEnabledEngines, 16) << " pid" << m_cmdLineAttachPid << '\n';
qDebug().nospace() << args << "engines=0x"
<< QString::number(m_cmdLineEnabledEngines, 16)
<< " pid" << m_cmdLineAttachPid << '\n';
return true;
}
......@@ -537,13 +539,15 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
{
// Do not fail the whole plugin if something goes wrong here
if (!parseArguments(arguments, errorMessage)) {
*errorMessage = tr("Error evaluating command line arguments: %1").arg(*errorMessage);
*errorMessage = tr("Error evaluating command line arguments: %1")
.arg(*errorMessage);
qWarning("%s\n", qPrintable(*errorMessage));
errorMessage->clear();
}
m_manager = new DebuggerManager;
const QList<Core::IOptionsPage *> engineOptionPages = m_manager->initializeEngines(m_cmdLineEnabledEngines);
const QList<Core::IOptionsPage *> engineOptionPages =
m_manager->initializeEngines(m_cmdLineEnabledEngines);
ICore *core = ICore::instance();
QTC_ASSERT(core, return false);
......@@ -889,9 +893,6 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
this, SLOT(activatePreviousMode()));
connect(m_manager, SIGNAL(debugModeRequested()),
this, SLOT(activateDebugMode()));
connect(m_manager, SIGNAL(statusChanged(int)),
this, SLOT(updateActions(int)));
connect(theDebuggerAction(SettingsDialog), SIGNAL(triggered()),
this, SLOT(showSettingsDialog()));
......@@ -1112,7 +1113,7 @@ void DebuggerPlugin::gotoLocation(const StackFrame &frame, bool setMarker)
void DebuggerPlugin::changeStatus(int status)
{
bool startIsContinue = (status == DebuggerInferiorStopped);
const bool startIsContinue = (status == DebuggerInferiorStopped);
ICore *core = ICore::instance();
if (startIsContinue) {
core->addAdditionalContext(m_gdbRunningContext);
......@@ -1121,6 +1122,27 @@ void DebuggerPlugin::changeStatus(int status)
core->removeAdditionalContext(m_gdbRunningContext);
core->updateContext();
}
const bool started = status == DebuggerInferiorRunning
|| status == DebuggerInferiorRunningRequested
|| status == DebuggerInferiorStopRequested
|| status == DebuggerInferiorStopped;
const bool starting = status == DebuggerProcessStartingUp;
//const bool running = status == DebuggerInferiorRunning;
const bool ready = status == DebuggerInferiorStopped
&& m_manager->startParameters()->startMode != AttachCore;
m_startExternalAction->setEnabled(!started && !starting);
m_attachExternalAction->setEnabled(!started && !starting);
#ifdef Q_OS_WIN
m_attachCoreAction->setEnabled(false);
#else
m_attachCoreAction->setEnabled(!started && !starting);
#endif
m_startRemoteAction->setEnabled(!started && !starting);
m_detachAction->setEnabled(ready);
}
void DebuggerPlugin::writeSettings() const
......@@ -1337,29 +1359,6 @@ void DebuggerPlugin::attachRemoteTcf()
runControl->start();
}
void DebuggerPlugin::updateActions(int status)
{
const bool started = status == DebuggerInferiorRunning
|| status == DebuggerInferiorRunningRequested
|| status == DebuggerInferiorStopRequested
|| status == DebuggerInferiorStopped;
const bool starting = status == DebuggerProcessStartingUp;
//const bool running = status == DebuggerInferiorRunning;
const bool ready = status == DebuggerInferiorStopped
&& m_manager->startParameters()->startMode != AttachCore;
m_startExternalAction->setEnabled(!started && !starting);
m_attachExternalAction->setEnabled(!started && !starting);
#ifdef Q_OS_WIN
m_attachCoreAction->setEnabled(false);
#else
m_attachCoreAction->setEnabled(!started && !starting);
#endif
m_startRemoteAction->setEnabled(!started && !starting);
m_detachAction->setEnabled(ready);
}
#include "debuggerplugin.moc"
Q_EXPORT_PLUGIN(DebuggerPlugin)
......@@ -94,7 +94,6 @@ private slots:
void setConfigValue(const QString &name, const QVariant &value);
void requestContextMenu(TextEditor::ITextEditor *editor,
int lineNumber, QMenu *menu);
void updateActions(int status);
void resetLocation();
void gotoLocation(const StackFrame &frame, bool setMarker);
......
......@@ -87,8 +87,7 @@ public:
virtual void interruptInferior() = 0;
virtual void shutdown() = 0;
virtual const DebuggerStartParameters &startParameters() const
{ return m_engine->startParameters(); }
virtual bool dumpersAvailable() const = 0;
signals:
void adapterStarted();
......@@ -111,9 +110,14 @@ signals:
void readyReadStandardError();
public:
virtual GdbAdapterState state() const { return m_state; }
GdbAdapterState state() const { return m_state; }
// Called by GdbEngine::handleAsyncOutput
void notifyInferiorExited();
protected:
virtual void setState(GdbAdapterState state) { m_state = state; }
void setState(GdbAdapterState state);
const DebuggerStartParameters &startParameters() const
{ return m_engine->startParameters(); }
GdbEngine * const m_engine;
GdbAdapterState m_state;
......
......@@ -59,6 +59,7 @@ private:
void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
bool isTrkAdapter() const { return false; }
bool dumpersAvailable() const { return false; }
void startAdapter();
void prepareInferior();
......
......@@ -59,6 +59,7 @@ private:
void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
bool isTrkAdapter() const { return false; }
bool dumpersAvailable() const { return false; }
void startAdapter();
void prepareInferior();
......
......@@ -271,45 +271,12 @@ void GdbEngine::connectAdapter()
this, SLOT(handleInferiorShutdownFailed(QString)));
connect(m_gdbAdapter, SIGNAL(adapterCrashed()),
m_manager, SLOT(exitDebugger()));
this, SLOT(handleAdapterCrashed()));
}
void GdbEngine::disconnectAdapter()
{
// Gdb Process interaction
disconnect(m_gdbAdapter, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(gdbProcError(QProcess::ProcessError)));
disconnect(m_gdbAdapter, SIGNAL(readyReadStandardOutput()),
this, SLOT(readGdbStandardOutput()));
disconnect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
this, SLOT(readGdbStandardError()));
disconnect(m_gdbAdapter, SIGNAL(adapterStarted()),
this, SLOT(handleAdapterStarted()));
disconnect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString)),
this, SLOT(handleAdapterStartFailed(QString)));
disconnect(m_gdbAdapter, SIGNAL(adapterShutDown()),
this, SLOT(handleAdapterShutDown()));
disconnect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)),
this, SLOT(handleAdapterShutdownFailed(QString)));
disconnect(m_gdbAdapter, SIGNAL(inferiorPrepared()),
this, SLOT(handleInferiorPrepared()));
disconnect(m_gdbAdapter, SIGNAL(inferiorPreparationFailed(QString)),
this, SLOT(handleInferiorPreparationFailed(QString)));
disconnect(m_gdbAdapter, SIGNAL(inferiorStarted()),
this, SLOT(handleInferiorStarted()));
disconnect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
this, SLOT(handleInferiorStartFailed(QString)));
disconnect(m_gdbAdapter, SIGNAL(inferiorShutDown()),
this, SLOT(handleInferiorShutDown()));
disconnect(m_gdbAdapter, SIGNAL(inferiorShutdownFailed(QString)),
this, SLOT(handleInferiorShutdownFailed(QString)));
disconnect(m_gdbAdapter, SIGNAL(adapterCrashed()),
m_manager, SLOT(exitDebugger()));
disconnect(m_gdbAdapter, 0, this, 0);
}
void GdbEngine::initializeVariables()
......@@ -386,9 +353,7 @@ void GdbEngine::gdbProcError(QProcess::ProcessError error)
showStatusMessage(msg);
showMessageBox(QMessageBox::Critical, tr("Error"), msg);
// act as if it was closed by the core
//if (kill)
m_manager->exitDebugger();
shutdown();
}
#if 0
......@@ -696,7 +661,7 @@ void GdbEngine::interruptInferior()
if (m_gdbAdapter->state() == AdapterNotRunning) {
debugMessage(_("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB"));
qq->notifyInferiorExited();
shutdown();
return;
}
......@@ -833,7 +798,7 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
showMessageBox(QMessageBox::Critical,
tr("Executable failed"), QString::fromLocal8Bit(msg));
showStatusMessage(tr("Process failed to start."));
exitDebugger();
shutdown();
}
return;
}
......@@ -1100,7 +1065,7 @@ void GdbEngine::handleAqcuiredInferior()
}
#endif
// nicer to see a bit of the world we live in
// It's nicer to see a bit of the world we live in.
reloadModules();
attemptBreakpointSynchronization();
}
......@@ -1110,19 +1075,21 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
const QByteArray reason = data.findChild("reason").data();
if (isExitedReason(reason)) {
qq->notifyInferiorExited();
// Give adapter a chance to take notice of regular exits.
m_gdbAdapter->notifyInferiorExited();
QString msg;
if (reason == "exited") {
msg = tr("Program exited with exit code %1")
msg = tr("Program exited with exit code %1.")
.arg(_(data.findChild("exit-code").toString()));
} else if (reason == "exited-signalled" || reason == "signal-received") {
msg = tr("Program exited after receiving signal %1")
msg = tr("Program exited after receiving signal %1.")
.arg(_(data.findChild("signal-name").toString()));
} else {
msg = tr("Program exited normally");
msg = tr("Program exited normally.");
}
showStatusMessage(msg);
postCommand(_("-gdb-exit"), CB(handleExit));
shutdown();
return;
}
......@@ -1421,7 +1388,7 @@ void GdbEngine::handleFileExecAndSymbols(const GdbResultRecord &response, const
showMessageBox(QMessageBox::Critical, tr("Starting executable failed"), msg);
QTC_ASSERT(status() == DebuggerInferiorRunning, /**/);
//interruptInferior();
qq->notifyInferiorExited();
shutdown();
}
}
......@@ -1441,7 +1408,7 @@ void GdbEngine::handleExecContinue(const GdbResultRecord &response, const QVaria
showMessageBox(QMessageBox::Critical, tr("Error"),
tr("Starting executable failed:\n") + QString::fromLocal8Bit(msg));
QTC_ASSERT(status() == DebuggerInferiorRunning, /**/);
qq->notifyInferiorExited();
shutdown();
}
}