diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 203bfc5b6b9e8b85671520fe615268fc89668633..2f665f3da53fa677455c3d91ba45c3c80a084b9d 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -150,7 +150,6 @@ void DebuggerManager::init() { m_status = -1; m_busy = false; - m_shutdown = false; m_attachedPID = 0; m_startMode = startInternal; @@ -578,7 +577,7 @@ void DebuggerManager::notifyInferiorExited() void DebuggerManager::notifyInferiorPidChanged(int pid) { //QMessageBox::warning(0, "PID", "PID: " + QString::number(pid)); - qDebug() << "PID: " << pid; + //qDebug() << "PID: " << pid; emit inferiorPidChanged(pid); } @@ -590,9 +589,10 @@ void DebuggerManager::showApplicationOutput(const QString &str) void DebuggerManager::shutdown() { //qDebug() << "DEBUGGER_MANAGER SHUTDOWN START"; - m_shutdown = true; - if (m_engine) + if (m_engine) { + //qDebug() << "SHUTTING DOWN ENGINE" << m_engine; m_engine->shutdown(); + } m_engine = 0; delete scriptEngine; @@ -835,10 +835,9 @@ void DebuggerManager::cleanupViews() void DebuggerManager::exitDebugger() { - if (m_shutdown) - return; - QTC_ASSERT(m_engine, return); - m_engine->exitDebugger(); + //qDebug() << "DebuggerManager::exitDebugger"; + if (m_engine) + m_engine->exitDebugger(); cleanupViews(); setStatus(DebuggerProcessNotReady); setBusyCursor(false); @@ -960,33 +959,6 @@ void DebuggerManager::dumpLog() ts << m_outputWindow->combinedContents(); } -#if 0 -// call after m_gdbProc exited. -void GdbEngine::procFinished() -{ - //qDebug() << "GDB PROCESS FINISHED"; - setStatus(DebuggerProcessNotReady); - showStatusMessage(tr("Done"), 5000); - q->m_breakHandler->procFinished(); - q->m_watchHandler->cleanup(); - m_stackHandler->m_stackFrames.clear(); - m_stackHandler->resetModel(); - m_threadsHandler->resetModel(); - if (q->m_modulesHandler) - q->m_modulesHandler->procFinished(); - q->resetLocation(); - setStatus(DebuggerProcessNotReady); - emit q->previousModeRequested(); - emit q->debuggingFinished(); - //exitDebugger(); - //showStatusMessage("Gdb killed"); - m_shortToFullName.clear(); - m_fullToShortName.clear(); - m_shared = 0; - q->m_busy = false; -} -#endif - void DebuggerManager::addToWatchWindow() { // requires a selection, but that's the only case we want... diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index bd10b7b025967d1793f5145304fd702dcaa0b46f..a3407a0aa59c4f410d3a711929805d872f6d972e 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -466,8 +466,6 @@ private: IDebuggerEngine *engine(); IDebuggerEngine *m_engine; DebuggerSettings m_settings; - // set during application shutdown - bool m_shutdown; }; } // namespace Internal diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 21313428aefbdc14eca3592321211140176a10b4..5034a0d9a4abd0dfe7d9c958c7255dc39e566d69 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -115,6 +115,8 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, connect(m_manager, SIGNAL(inferiorPidChanged(qint64)), this, SLOT(bringApplicationToForeground(qint64)), Qt::QueuedConnection); + connect(this, SIGNAL(stopRequested()), + m_manager, SLOT(exitDebugger())); } void DebuggerRunControl::start() @@ -148,17 +150,21 @@ void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data) void DebuggerRunControl::stop() { - m_manager->exitDebugger(); + //qDebug() << "DebuggerRunControl::stop"; + m_running = false; + emit stopRequested(); } void DebuggerRunControl::debuggingFinished() { m_running = false; + //qDebug() << "DebuggerRunControl::finished"; //emit addToOutputWindow(this, tr("Debugging %1 finished").arg(m_executable)); emit finished(); } bool DebuggerRunControl::isRunning() const { + //qDebug() << "DebuggerRunControl::isRunning" << m_running; return m_running; } diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 0c6d979c0107f89e79ce196beb4511ac5e577abb..7b73178d1031df8a7875ab9f4eba3c56cf47dfed 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -82,6 +82,9 @@ public: virtual void stop(); virtual bool isRunning() const; +signals: + void stopRequested(); + private slots: void debuggingFinished(); void slotAddToOutputWindowInline(const QString &output); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 0641dac2114aeb7bcf20bb2a35ac90c189adf41f..7f99a0a9b3e2e170c619a38b58038847a27cc2e6 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -257,6 +257,8 @@ GdbEngine::GdbEngine(DebuggerManager *parent) GdbEngine::~GdbEngine() { + // prevent sending error messages afterwards + m_gdbProc.disconnect(this); } void GdbEngine::initializeConnections() @@ -386,6 +388,11 @@ void GdbEngine::readDebugeeOutput(const QByteArray &data) data.constData(), data.length(), &m_outputCodecState)); } +void GdbEngine::debugMessage(const QString &msg) +{ + emit gdbOutputAvailable("debug:", msg); +} + // called asyncronously as response to Gdb stdout output in // gdbResponseAvailable() void GdbEngine::handleResponse() @@ -656,7 +663,7 @@ void GdbEngine::interruptInferior() sendCommand("-exec-interrupt", GdbExecInterrupt); qq->notifyInferiorStopped(); #else - qDebug() << "CANNOT STOP INFERIOR" << m_gdbProc.pid(); + debugMessage(QString("CANNOT STOP INFERIOR %1").arg(m_gdbProc.pid())); if (interruptChildProcess(m_gdbProc.pid())) qq->notifyInferiorStopped(); #endif @@ -666,12 +673,12 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) { int pid = pid0.toInt(); if (pid == 0) { - qDebug() << "Cannot parse PID from " << pid0; + debugMessage(QString("Cannot parse PID from %1").arg(pid0)); return; } if (pid == q->m_attachedPID) return; - qDebug() << "FOUND PID " << pid; + debugMessage(QString("FOUND PID %1").arg(pid)); q->m_attachedPID = pid; qq->notifyInferiorPidChanged(pid); } @@ -686,7 +693,7 @@ void GdbEngine::sendCommand(const QString &command, int type, const QVariant &cookie, bool needStop, bool synchronized) { if (m_gdbProc.state() == QProcess::NotRunning) { - //qDebug() << "NO GDB PROCESS RUNNING, CMD IGNORED:" << command; + debugMessage("NO GDB PROCESS RUNNING, CMD IGNORED: " + command); return; } @@ -718,9 +725,7 @@ void GdbEngine::sendCommand(const QString &command, int type, m_cookieForToken[currentToken()] = cmd; - //qDebug() << ""; if (!command.isEmpty()) { - //qDebug() << qPrintable(currentTime()) << "RUNNING" << cmd.command; m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); //emit gdbInputAvailable(QString(), " " + currentTime()); //emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command); @@ -920,8 +925,8 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type, break; default: - qDebug() << "FIXME: GdbEngine::handleResult: " - "should not happen" << type; + debugMessage(QString("FIXME: GdbEngine::handleResult: " + "should not happen %1").arg(type)); break; } } @@ -930,7 +935,7 @@ void GdbEngine::executeDebuggerCommand(const QString &command) { //createGdbProcessIfNeeded(); if (m_gdbProc.state() == QProcess::NotRunning) { - qDebug() << "NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: " << command; + debugMessage("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: " + command); return; } @@ -938,11 +943,6 @@ void GdbEngine::executeDebuggerCommand(const QString &command) cmd.command = command; cmd.type = -1; - //m_cookieForToken[currentToken()] = cmd; - //++currentToken(); - - //qDebug() << ""; - //qDebug() << currentTime() << "Running command: " << cmd.command; emit gdbInputAvailable(QString(), cmd.command); m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); } @@ -969,7 +969,7 @@ void GdbEngine::handleQueryPwd(const GdbResultRecord &record) m_pwd = record.data.findChild("consolestreamoutput").data(); m_pwd = m_pwd.trimmed(); #endif - //qDebug() << "PWD RESULT:" << m_pwd; + debugMessage("PWD RESULT: " + m_pwd); } } @@ -1146,8 +1146,8 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) QString msg = data.findChild("consolestreamoutput").data(); if (msg.contains("Stopped due to shared library event") || reason.isEmpty()) { if (qq->wantsSelectedPluginBreakpoints()) { - qDebug() << "SHARED LIBRARY EVENT " << data.toString(); - qDebug() << "PATTERN" << qq->selectedPluginBreakpointsPattern(); + debugMessage("SHARED LIBRARY EVENT: " + data.toString()); + debugMessage("PATTERN: " + qq->selectedPluginBreakpointsPattern()); sendCommand("sharedlibrary " + qq->selectedPluginBreakpointsPattern()); continueInferior(); q->showStatusMessage(tr("Loading %1...").arg(QString(data.toString()))); @@ -1182,6 +1182,8 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) + data.findChild("signal-name").toString(); } q->showStatusMessage(msg); + // FIXME: shouldn't this use a statis change? + debugMessage("CALLING PARENT EXITDEBUGGER"); q->exitDebugger(); return; } @@ -1193,21 +1195,21 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (qq->skipKnownFrames()) { if (reason == "end-stepping-range" || reason == "function-finished") { GdbMi frame = data.findChild("frame"); - //qDebug() << frame.toString(); + //debugMessage(frame.toString()); m_currentFrame = frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'; QString funcName = frame.findChild("func").data(); QString fileName = frame.findChild("file").data(); if (isLeavableFunction(funcName, fileName)) { - //qDebug() << "LEAVING" << funcName; + //debugMessage("LEAVING" + funcName); ++stepCounter; q->stepOutExec(); //stepExec(); return; } if (isSkippableFunction(funcName, fileName)) { - //qDebug() << "SKIPPING" << funcName; + //debugMessage("SKIPPING" + funcName); ++stepCounter; q->stepExec(); return; @@ -1227,7 +1229,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (reason == "breakpoint-hit") { q->showStatusMessage(tr("Stopped at breakpoint")); GdbMi frame = data.findChild("frame"); - //qDebug() << "HIT BREAKPOINT: " << frame.toString(); + //debugMessage("HIT BREAKPOINT: " + frame.toString()); m_currentFrame = frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'; @@ -1243,7 +1245,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) return; } - qDebug() << "STOPPED FOR UNKNOWN REASON" << data.toString(); + debugMessage("STOPPED FOR UNKNOWN REASON: " + data.toString()); // Ignore it. Will be handled with full response later in the // JumpToLine or RunToFunction handlers #if 1 @@ -1310,7 +1312,7 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response) QString msg = response.data.findChild("consolestreamoutput").data(); QRegExp supported("GNU gdb(.*) (\\d+)\\.(\\d+)(\\.(\\d+))?"); if (supported.indexIn(msg) == -1) { - qDebug() << "UNSUPPORTED GDB VERSION " << msg; + debugMessage("UNSUPPORTED GDB VERSION " + msg); QStringList list = msg.split("\n"); while (list.size() > 2) list.removeLast(); @@ -1331,7 +1333,7 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response) m_gdbVersion = 10000 * supported.cap(2).toInt() + 100 * supported.cap(3).toInt() + 1 * supported.cap(5).toInt(); - //qDebug() << "GDB VERSION " << m_gdbVersion; + //debugMessage(QString("GDB VERSION: %1").arg(m_gdbVersion)); } } } @@ -1387,7 +1389,7 @@ QString GdbEngine::fullName(const QString &fileName) if (fileName.isEmpty()) return QString(); QString full = m_shortToFullName.value(fileName, QString()); - //qDebug() << "RESOLVING: " << fileName << full; + //debugMessage("RESOLVING: " + fileName + " " + full); if (!full.isEmpty()) return full; QFileInfo fi(fileName); @@ -1397,7 +1399,7 @@ QString GdbEngine::fullName(const QString &fileName) #ifdef Q_OS_WIN full = QDir::cleanPath(full); #endif - //qDebug() << "STORING: " << fileName << full; + //debugMessage("STORING: " + fileName + " " + full); m_shortToFullName[fileName] = full; m_fullToShortName[full] = fileName; return full; @@ -1425,22 +1427,29 @@ void GdbEngine::shutdown() void GdbEngine::exitDebugger() { - //qDebug() << "EXITING: " << m_gdbProc.state(); - if (m_gdbProc.state() == QProcess::Starting) + debugMessage(QString("GDBENGINE EXITDEBUFFER: %1").arg(m_gdbProc.state())); + if (m_gdbProc.state() == QProcess::Starting) { + debugMessage(QString("WAITING FOR GDB STARTUP TO SHUTDOWN: %1") + .arg(m_gdbProc.state())); m_gdbProc.waitForStarted(); + } if (m_gdbProc.state() == QProcess::Running) { + debugMessage(QString("WAITING FOR RUNNING GDB TO SHUTDOWN: %1") + .arg(m_gdbProc.state())); interruptInferior(); sendCommand("kill"); sendCommand("-gdb-exit"); // 20s can easily happen when loading webkit debug information m_gdbProc.waitForFinished(20000); if (m_gdbProc.state() != QProcess::Running) { + debugMessage(QString("FORCING TERMINATION: %1") + .arg(m_gdbProc.state())); m_gdbProc.terminate(); m_gdbProc.waitForFinished(20000); } } if (m_gdbProc.state() != QProcess::NotRunning) - qDebug() << "PROBLEM STOPPING DEBUGGER"; + debugMessage("PROBLEM STOPPING DEBUGGER"); m_outputCollector.shutdown(); initializeVariables(); @@ -1462,7 +1471,7 @@ bool GdbEngine::startDebugger() QString fileName = '"' + fi.absoluteFilePath() + '"'; if (m_gdbProc.state() != QProcess::NotRunning) { - qDebug() << "GDB IS ALREADY RUNNING!"; + debugMessage("GDB IS ALREADY RUNNING!"); return false; } @@ -1636,16 +1645,16 @@ void GdbEngine::handleStart(const GdbResultRecord &response) QString msg = response.data.findChild("consolestreamoutput").data(); QRegExp needle("0x([0-9a-f]+) <" + startSymbolName() + "\\+.*>:"); if (needle.indexIn(msg) != -1) { - //qDebug() << "STREAM: " << msg << needle.cap(1); + //debugMessage("STREAM: " + msg + " " + needle.cap(1)); sendCommand("tbreak *0x" + needle.cap(1)); m_waitingForFirstBreakpointToBeHit = true; sendCommand("-exec-run"); qq->notifyInferiorRunningRequested(); } else { - qDebug() << "PARSING START ADDRESS FAILED" << msg; + debugMessage("PARSING START ADDRESS FAILED: " + msg); } } else if (response.resultClass == GdbResultError) { - qDebug() << "PARSING START ADDRESS FAILED" << response.toString(); + debugMessage("PARSING START ADDRESS FAILED: " + response.toString()); } } @@ -1740,12 +1749,12 @@ void GdbEngine::setTokenBarrier() void GdbEngine::setDebugDumpers(bool on) { if (on) { - qDebug() << "SWITCHING ON DUMPER DEBUGGING"; + debugMessage("SWITCHING ON DUMPER DEBUGGING"); sendCommand("set unwindonsignal off"); q->breakByFunction("qDumpObjectData440"); //updateLocals(); } else { - qDebug() << "SWITCHING OFF DUMPER DEBUGGING"; + debugMessage("SWITCHING OFF DUMPER DEBUGGING"); sendCommand("set unwindonsignal on"); } } diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index 0d710e359cf7139c7f45e3d98448a7fa9090d8c9..ee5de645c3de8a1af53b7efa8773153cded0ce7c 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -193,6 +193,7 @@ private: void handleShowVersion(const GdbResultRecord &response); void handleQueryPwd(const GdbResultRecord &response); void handleQuerySources(const GdbResultRecord &response); + void debugMessage(const QString &msg); OutputCollector m_outputCollector; QTextCodec *m_outputCodec;