VS Code output capture discards output between DAP exited and terminated
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 45/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- typescript, vscode
- Bereich
- devtools
Rechercherichtung
Read src/utils/debugSessionTracker.ts, especially the message callback gate and observe/endSession handling for exited; then inspect the output buffer ownership and generation checks described in the report. Reproduce with the linked harness and verify output after exited is retained and paginated while execution stays ended, stale generations are rejected, and stop/disposal controls still pass.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Summary
With output capture enabled, DebugMCP records output before a DAP exited
event, but drops subsequent output delivered before terminated. The tracker
treats debuggee exit as the end of its message-observation lifetime, even though
the adapter can still emit debugger output before the debug session ends.
Execution-state tracking and output-capture lifetime need separate handling.
The session should remain execution-ended after exited; preserving its final
output must not recreate paused execution state or revive a stopped tracker.
Environment and assistance
- Microsoft/DebugMCP source commit:
d0b4a334a6a3d8d600c5aa75ec60d9de272af3c4. - Test baseline: Windows x64, Node.js
v24.22.1, root package version 2.4.4. - Actual compiled
DebugSessionTracker,DebugOutputBuffer,DebuggingExecutor
andDebuggingHandlerimplementations, with a synthetic VS Code tracker-factory
API and synthetic harmless DAP output markers. - This investigation and report were prepared with assistance from OpenAI
Codex desktop 26.1021.31345, build 21828, verified 2026-10-25.
This identifies the authoring/review environment. The automated reproduction
runs directly under Node and calls the production output handler; it does not
send requests through a Codex client or an MCP transport.
No real editor, debug adapter or debuggee is started. Capture is enabled solely
by the test buffer's local provider; installed editor or user settings are not
changed.
Reproduction steps
-
Prepare a separate Microsoft/DebugMCP checkout at the pinned revision:
git clone https://github.com/microsoft/DebugMCP.git cd DebugMCP git checkout d0b4a334a6a3d8d600c5aa75ec60d9de272af3c4 npm ci --ignore-scripts npm run compile -
Clone this reproduction repository's
mainbranch in a separate directory
and run the harness. Replace<absolute-path-to-DebugMCP>with the absolute
path of the Microsoft/DebugMCP checkout prepared in step 1:git clone --branch main https://github.com/hahnfk/debugmcp-repro.git cd debugmcp-repro node scripts/review/debug-output-after-exited.cjs --debugmcp-root "<absolute-path-to-DebugMCP>"Reproduction files on
main: -
The harness constructs the real buffer with an enabled local opt-in provider,
passes it to the real session tracker, and obtains tracker callbacks through
its registered public factory. The real executor and handler read captured
output from that tracker. -
Through
onDidSendMessage, it delivers a session's DAP events in this order:output("before-exited") exited(exitCode: 0) output("after-exited-one") output("after-exited-two") terminatedEach output is a harmless
consolemarker beginning with the same explicit
prefix. Each DAP event has standardseq,type,eventandbodyfields. -
It reads the first marker through the production output handler before
exited, using a one-entry page limit. After the remaining events, it reuses
the returned cursor to read incrementally until empty, then reads the full
filtered history. It also verifies that the public tracker remains
execution-ended afterexitedand after the later output.
Seven controls check normal pagination and post-end retention, session
isolation, disabled capture, three actual owner-stop callbacks, and protection
against stale tracker generations sharing a session ID. A late stopped event
in the normal lifecycle control must not restore execution after exited.
The default command checks the expected fixed behavior and exits nonzero on the
reviewed commit. To require the exact current failure signature together with
all controls and cleanup checks, use:
node scripts/review/debug-output-after-exited.cjs --debugmcp-root "<absolute-path-to-DebugMCP>" --expect-current-bug
A disabled-capture error, missing session, unrelated exception or failed control
does not count as reproducing this output-loss bug.
Expected result
The first read returns before-exited. Incremental reads then return
after-exited-one and after-exited-two exactly once, followed by an empty page.
The full history contains all three markers in order. Each incremental page
respects the explicit one-entry limit.
The session remains execution-ended after exited. Output capture should not
revive paused state, admit a superseded tracker generation, or recreate history
after tracker disposal. Existing history remains readable within the existing
buffer limits after the session ends.
Actual result
On the reviewed commit, only before-exited is retained. The first incremental
read after the remaining events returns no entries, its cursor does not advance,
and it reports no more output. The full filtered history likewise contains only
the first marker, despite both subsequent output events reaching the production
tracker callback before terminated.
All seven controls pass, and execution remains ended. The default regression
exits with code 1; --expect-current-bug exits with code 0 only when the exact
first-marker-only loss and all controls/cleanup are confirmed. Session IDs and
cursor values in the output are local observations, not reproduction constants.
The recorded evidence
contains both central runs, event traces and incremental reads, all seven
controls, execution-state checks, factory/subscription/buffer cleanup and
source/compiled-module hashes.
Protocol and adapter-source context
The DAP session-end overview
distinguishes a debuggee's exited event from the debugging session's
terminated event. It does not require all debugger output to precede exited.
The controlled sequence above follows that distinction; the harness does not
claim to have observed an installed adapter flushing output in this order.
There is also a concrete static example in LLDB-DAP source at pinned LLVM commit
06eaf2c9557dfc54a375f2e1d033e493639d02a0. Its
process-exit path
sends exited before calling SendTerminatedEvent. The
termination helper
runs configured terminate commands before sending terminated on its first
invocation. Those commands
delegate to the command-output path,
which sends nonempty command output to the console.
Configured terminate commands that produce output can therefore place console
output between these events. This is source corroboration, not an LLDB runtime
test performed by this reproduction.
Cause
The public tracker callback
gates every incoming adapter message on its current execution-state entry.
On exited,
observe calls endSession,
which
removes that execution-state entry.
Later output callbacks fail the gate and never reach the actual buffer. Existing
buffered data survives, which explains why the first marker remains readable.
Preserving final output should retain appropriate capture ownership and
generation checks without recreating execution state after debuggee exit.
Scope and cleanup
The harness uses actual compiled tracker, buffer, executor and handler methods.
It does not write their private fields or replace their methods. Test seams are
the public VS Code factory/termination API boundary, the local capture-enabled
provider and a logger sink that counts unexpected internal errors. The shared
loader's inert vscode import is sufficient; no additional import hook is used.
Output reads use the production handler with an explicit session ID and
prefix/category filters. The test does not cover MCP transport, live editor
events, buffer eviction pressure or new redaction rules. All markers are
synthetic and contain no secrets.
Post-stop drop controls use onWillStopSession, adapter onExit, and VS Code's
onDidTerminateDebugSession. They do not prescribe dropping every output event
solely because a DAP terminated message has arrived. The generation control
recreates a tracker for the same session ID and confirms that old output/stop
callbacks and old cursors cannot affect the replacement generation.
Each fixture disposes its real tracker and verifies removal of factory and
termination subscriptions, buffer clearing, rejection of capture from retained
old callbacks, absence of execution-state reactivation, and refusal to create
another tracker through the disposed public factory. Unexpected logged errors
fail the oracle. A separate eight-second
deadline bounds the harness.
Related reports and changes
Issue #178 requested output
retrieval; merged PR #185
introduced the capture path. This report concerns that feature's lifecycle after
debuggee exit, while preserving its existing opt-in, bounds, filters and session
isolation.
- Vorherrschende Sprache
- TypeScript
- Sterne
- 580
- Forks
- 63
- Ø Merge
- 1 T. 17 Std.
- Gemergte PRs (30 T.)
- 11
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus microsoft/DebugMCP
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 48/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 56/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 58/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 66/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 70/100
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in microsoft/DebugMCP
Ähnliche Issues
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 85/100
formbricks/formbricks#9918 ·
Maintainer antworten meist innerhalb von 1 Tag
-
enhancement
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
thecodacus/pithagoras#364 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 72/100
openclimatefix/quartz-frontend#823 ·
Maintainer antworten meist innerhalb von 4 Tagen
-
area:agent-manager community needs-triage
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
Maintainer antworten meist innerhalb von 1 Tag
-
`contacts.create` posts to `/audiences/undefined/contacts` when `audienceId` is undefinedEvtl. vergeben @RaphaelFakhri hat das heute übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
resend/resend-node#1176 ·
Maintainer antworten meist innerhalb von 1 Tag