diff options
Diffstat (limited to 'src/plugins/debugger/cdb/cdbdebugengine.cpp')
-rw-r--r-- | src/plugins/debugger/cdb/cdbdebugengine.cpp | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index 11f37d15f1..c7f0405570 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -302,6 +302,7 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *manager, m_dumper(new CdbDumperHelper(manager, &m_cif)), m_currentThreadId(-1), m_eventThreadId(-1), + m_interrupted(false), m_watchTimer(-1), m_debugEventCallBack(engine), m_engine(engine), @@ -445,6 +446,7 @@ void CdbDebugEnginePrivate::clearForRun() m_breakEventMode = BreakEventHandle; m_eventThreadId = -1; + m_interrupted = false; cleanStackTrace(); } @@ -1026,6 +1028,9 @@ bool CdbDebugEngine::step(unsigned long executionStatus) warning(msgStepFailed(executionStatus, m_d->m_currentThreadId, msgDebuggerCommandFailed(command, hr))); } if (success) { + // Oddity: Step into will first break at the calling function. Ignore + if (executionStatus == DEBUG_STATUS_STEP_INTO || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO) + m_d->m_breakEventMode = CdbDebugEnginePrivate::BreakEventIgnoreOnce; startWatchTimer(); setState(InferiorRunning, Q_FUNC_INFO, __LINE__); } else { @@ -1169,7 +1174,9 @@ bool CdbDebugEnginePrivate::interruptInterferiorProcess(QString *errorMessage) qDebug() << Q_FUNC_INFO << "\n ex=" << executionStatus; } - if (!DebugBreakProcess(m_hDebuggeeProcess)) { + if (DebugBreakProcess(m_hDebuggeeProcess)) { + m_interrupted = true; + } else { *errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Utils::winErrorMessage(GetLastError())); return false; } @@ -1704,12 +1711,34 @@ ULONG CdbDebugEnginePrivate::updateThreadList() QList<ThreadData> threads; ULONG currentThreadId; QString errorMessage; + // When interrupting, an artifical thread with a breakpoint is created. if (!CdbStackTraceContext::getThreads(m_cif, true, &threads, ¤tThreadId, &errorMessage)) m_engine->warning(errorMessage); manager()->threadsHandler()->setThreads(threads); return currentThreadId; } +// Figure out the thread to run the dumpers in (see notes on. +// CdbDumperHelper). Avoid the artifical threads created by interrupt +// and threads that are in waitFor(). +// A stricter version could only use the thread if it is the event +// thread of a step or breakpoint hit (see CdbDebugEnginePrivate::m_interrupted). + +static inline unsigned long dumperThreadId(const QList<StackFrame> &frames, + unsigned long currentThread) +{ + if (frames.empty()) + return CdbDumperHelper::InvalidDumperCallThread; + if (frames.at(0).function == QLatin1String(CdbStackTraceContext::winFuncDebugBreakPoint)) + return CdbDumperHelper::InvalidDumperCallThread; + const int waitCheckDepth = qMin(frames.size(), 5); + static const QString waitForPrefix = QLatin1String(CdbStackTraceContext::winFuncWaitForPrefix); + for (int f = 0; f < waitCheckDepth; f++) + if (frames.at(f).function.startsWith(waitForPrefix)) + return CdbDumperHelper::InvalidDumperCallThread; + return currentThread; +} + void CdbDebugEnginePrivate::updateStackTrace() { if (debugCDB) @@ -1750,11 +1779,19 @@ void CdbDebugEnginePrivate::updateStackTrace() CdbDebugEngine::tr("Thread %1: No debug information available (%2).").arg(m_currentThreadId).arg(topFunction); m_engine->warning(msg); } - + // Set up dumper with a thread (or invalid) + const unsigned long dumperThread = dumperThreadId(stackFrames, m_currentThreadId); + if (debugCDB) + qDebug() << "updateStackTrace() current: " << m_currentThreadId << " dumper=" << dumperThread; + m_dumper->setDumperCallThread(dumperThread); + // Display frames manager()->stackHandler()->setFrames(stackFrames); m_firstActivatedFrame = true; if (current >= 0) { manager()->stackHandler()->setCurrentIndex(current); + // First time : repaint + if (m_dumper->isEnabled() && m_dumper->state() != CdbDumperHelper::Initialized) + QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); m_engine->activateFrame(current); } manager()->watchHandler()->updateWatchers(); |