feat(java): implement pause command and per-breakpoint suspend policy#25
Conversation
Add DAP pause support to JDI adapter (vm.suspend / thread.suspend) and introduce optional suspendPolicy parameter for breakpoints to control whether all threads or only the event thread are suspended on breakpoint hit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Wire threadId through MCP tool → server → SessionManager → DAP so callers can pause a specific thread instead of the entire VM. Defaults to 0 (all threads) when omitted. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Manual Test Report — Java/JDI Debugging Setup: mcp-debugger feat/pause-and-suspend-policy → Java Swing application via JDWP attach on localhost:5009
pause_execution(sessionId) → {success: true}
pause_execution(sessionId, threadId: 1) → {success: true}
set_breakpoint(file: "...", line: 315, condition: "true", suspendPolicy: "all") → verified
set_breakpoint(file: "...", line: 315, condition: "true", suspendPolicy: "thread") → verified |
- Add list_threads tool to expose DAP threads command via MCP - Wire threadId through SessionManager.listThreads → DAP - Add unit tests for: list_threads, pause with threadId, set_breakpoint with suspendPolicy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add targeted tests for uncovered PR diff lines: - listThreads in session-manager-operations (success, errors, edge cases) - pause with optional threadId parameter - setBreakpoint with suspendPolicy in DAP request - handleListThreads error paths in server - list_threads missing sessionId validation Remove dead code in handleListThreads where SessionTerminatedError, SessionNotFoundError, and ProxyNotRunningError checks were unreachable (all are McpError subclasses caught by the preceding instanceof check). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Thanks @Finomosec! Great contribution — the pause implementation fills a real gap in the JDI adapter, and the per-breakpoint suspend policy is a smart addition for multi-threaded Java debugging. The thorough manual test report was appreciated too. We also noticed that |
Add long-running pause_test example programs for all 6 languages (Python, JavaScript, Java, Go, Rust, .NET) to enable testing of pause_execution across all adapters. Each program runs an infinite loop with a 500ms sleep and incrementing counter variable. Also fix inaccurate documentation on pause_execution's threadId parameter — it's standard DAP, not Java-only as PR #25 claimed. - Replace examples/javascript/pause_test.js (ran instantly) with infinite setInterval loop - Delete examples/pause_test.py (used input(), unusable in automated debugging) - Remove "Only supported by the Java/JDI adapter" from threadId description in server.ts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
pausecommand — supports both VM-wide (vm.suspend()) and thread-specific (ThreadReference.suspend()) pause based onthreadIdparametersuspendPolicyparameter ("all"|"thread") toset_breakpointMCP tool, controlling whether all threads or only the event thread are suspended on breakpoint hitcontinuenow uses thread-specific resume when the last stop only suspended a single threadthreadIdparameter topause_executionMCP toollist_threadsMCP tool exposing DAPthreadscommandMotivation
Several gaps in the JDI Java adapter:
pause_executionMCP tool was wired up in server.ts + SessionManager but the JDI adapter had nocase "pause"handler — requests fell through to "Unsupported command"SUSPEND_ALL, freezing the entire VM on every hit. For multi-threaded applications (e.g. web servers),SUSPEND_EVENT_THREADis often preferable to keep other threads runninglist_threadstool despite JDI handleThreads being implementedChanges
JdiDapServer.javahandlePause(),suspendPolicyinsetBreakpointOnClass(), thread-awarehandleContinue(),lastStopAllThreadstrackingpackages/shared/src/models/index.tssuspendPolicy?: 'all' | 'thread'onBreakpointinterfacesrc/server.tssuspendPolicy+threadIdparams,list_threadstool,handleListThreads()src/session/session-manager-operations.tssuspendPolicy+threadIdpassthrough,listThreads()methodTest plan
npx tsc --noEmit— no type errorsnpx vitest run tests/core/unit/server/— 78 tests pass (includes new tests for pause+threadId, list_threads, suspendPolicy)npx vitest run tests/unit/server-coverage.test.ts— 40 tests passpause_execution(VM-wide) — VM pauses, stack readablepause_executionwiththreadId: 1— specific thread pausessuspendPolicy: "all"— all threads stop on hitsuspendPolicy: "thread"— only event thread stops on hit🤖 Generated with Claude Code