diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-11-24 16:17:27 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-12-02 14:11:25 +0000 |
commit | c3f03bbff1db14dc5b5436d8aef834512207d498 (patch) | |
tree | 279d2fdf57c1155392c31ba31a6291c68cb8d71c /src/plugins | |
parent | ec5a886d4b92a18669d5bbd01b43a57f7d81b856 (diff) |
Support multiple QML engines in V4 debugger
Whenever the debugger is paused, there is exactly one engine that
caused the debuggerPaused() slot to be called. We can only interact
with that engine in any meaningful way.
Of course you can shoot yourself in the foot with this tool. You can,
for example, set a breakpoint that will be hit by multiple engines and
then get confused about which engine just hit the breakpoint. Similar
things are also possible with other kinds of debuggers, though. If this
becomes a problem we can add an engine ID to the responses.
Also, this does not fix the other debug services. So you might still
not see the "correct" locals and expressions from the
QQmlEngineDebugService while the debugger is not paused.
Task-number: QTBUG-49615
Change-Id: Ie044f0aedb51481c4cf851635d7c12839251cbd0
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
Diffstat (limited to 'src/plugins')
5 files changed, 55 insertions, 19 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp index 6198e2c039..014de1f4cb 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp @@ -189,6 +189,12 @@ void QV4Debugger::setBreakOnThrow(bool onoff) m_breakOnThrow = onoff; } +void QV4Debugger::clearPauseRequest() +{ + QMutexLocker locker(&m_lock); + m_pauseRequested = false; +} + QV4Debugger::ExecutionState QV4Debugger::currentExecutionState() const { ExecutionState state; diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h index adc58141d0..8662259264 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h @@ -124,6 +124,8 @@ public: void setBreakOnThrow(bool onoff); + void clearPauseRequest(); + // used for testing struct ExecutionState { diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp index da43257b24..8bd9547032 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp @@ -44,22 +44,19 @@ QV4DebuggerAgent::QV4DebuggerAgent(QV4DebugServiceImpl *debugService) : m_breakOnThrow(false), m_debugService(debugService) {} -QV4Debugger *QV4DebuggerAgent::firstDebugger() const +QV4Debugger *QV4DebuggerAgent::pausedDebugger() const { - // Currently only 1 single engine is supported, so: - if (m_debuggers.isEmpty()) - return 0; - else - return m_debuggers.first(); + foreach (QV4Debugger *debugger, m_debuggers) { + if (debugger->state() == QV4Debugger::Paused) + return debugger; + } + return 0; } bool QV4DebuggerAgent::isRunning() const { - // Currently only 1 single engine is supported, so: - if (QV4Debugger *debugger = firstDebugger()) - return debugger->state() == QV4Debugger::Running; - else - return false; + // "running" means none of the engines are paused. + return pausedDebugger() == 0; } void QV4DebuggerAgent::debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason) @@ -221,4 +218,10 @@ void QV4DebuggerAgent::setBreakOnThrow(bool onoff) } } +void QV4DebuggerAgent::clearAllPauseRequests() +{ + foreach (QV4Debugger *debugger, m_debuggers) + debugger->clearPauseRequest(); +} + QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h index d133c6954b..dea9d74088 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.h @@ -46,7 +46,7 @@ class QV4DebuggerAgent : public QObject public: QV4DebuggerAgent(QV4DebugServiceImpl *m_debugService); - QV4Debugger *firstDebugger() const; + QV4Debugger *pausedDebugger() const; bool isRunning() const; void addDebugger(QV4Debugger *debugger); @@ -64,6 +64,7 @@ public: bool breakOnThrow() const { return m_breakOnThrow; } void setBreakOnThrow(bool onoff); + void clearAllPauseRequests(); public slots: void debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp index dbfbcb25bb..505617b8f9 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp @@ -271,7 +271,11 @@ public: int toFrame = arguments.value(QStringLiteral("toFrame")).toInt(fromFrame + 10); // no idea what the bottom property is for, so we'll ignore it. - QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); + if (!debugger) { + createErrorResponse(QStringLiteral("Debugger has to be paused to retrieve backtraces.")); + return; + } QJsonArray frameArray; QVector<QV4::StackFrame> frames = debugger->stackTrace(toFrame); @@ -308,7 +312,12 @@ public: const int frameNr = arguments.value(QStringLiteral("number")).toInt( debugService->selectedFrame()); - QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); + if (!debugger) { + createErrorResponse(QStringLiteral("Debugger has to be paused to retrieve frames.")); + return; + } + QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1); if (frameNr < 0 || frameNr >= frames.size()) { createErrorResponse(QStringLiteral("frame command has invalid frame number")); @@ -341,7 +350,12 @@ public: debugService->selectedFrame()); const int scopeNr = arguments.value(QStringLiteral("number")).toInt(0); - QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); + if (!debugger) { + createErrorResponse(QStringLiteral("Debugger has to be paused to retrieve scope.")); + return; + } + QVector<QV4::StackFrame> frames = debugger->stackTrace(frameNr + 1); if (frameNr < 0 || frameNr >= frames.size()) { createErrorResponse(QStringLiteral("scope command has invalid frame number")); @@ -399,7 +413,12 @@ public: // decypher the payload: QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); - QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); + if (!debugger) { + createErrorResponse(QStringLiteral("Debugger has to be paused in order to continue.")); + return; + } + debugService->debuggerAgent.clearAllPauseRequests(); if (arguments.empty()) { debugger->resume(QV4Debugger::FullThrottle); @@ -507,7 +526,12 @@ public: } // do it: - QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); + QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); + if (!debugger) { + createErrorResponse(QStringLiteral("Debugger has to be paused to retrieve scripts.")); + return; + } + GatherSourcesJob job(debugger->engine()); debugger->runInEngine(&job); @@ -562,8 +586,8 @@ public: virtual void handleRequest() { - QV4Debugger *debugger = debugService->debuggerAgent.firstDebugger(); - if (debugger->state() == QV4Debugger::Paused) { + QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); + if (debugger) { QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); QString expression = arguments.value(QStringLiteral("expression")).toString(); const int frame = arguments.value(QStringLiteral("frame")).toInt(0); |