Skip to content

Fix: Prevent multiple debug sessions spawning when F5 is held down#17250

Open
ankitsharma101 wants to merge 5 commits intoeclipse-theia:masterfrom
ankitsharma101:fix/f5-multiple-debug-sessions
Open

Fix: Prevent multiple debug sessions spawning when F5 is held down#17250
ankitsharma101 wants to merge 5 commits intoeclipse-theia:masterfrom
ankitsharma101:fix/f5-multiple-debug-sessions

Conversation

@ankitsharma101
Copy link
Copy Markdown
Contributor

What it does
Fixes #14639. When holding down F5 while paused at a breakpoint, Theia would spawn multiple concurrent debug sessions instead of simply continuing the paused session.
Root causes identified:

The START keybinding used when: '!inDebugMode' which could briefly evaluate to true during async state transitions between sessions
The CONTINUE keybinding used when: 'inDebugMode' which is true for both running and stopped states, causing ambiguity
The DebugSessionManager.start() method updated context keys only after async setup completed, leaving a window where repeated F5 presses could bypass the keybinding guards
The hacky isEnabled: () => this.manager.state !== DebugState.Inactive on the CONTINUE command (introduced in #14641) masked the root cause without fixing it

Changes:

Replace when: '!inDebugMode' with when: 'debugState == inactive' for the START keybinding — precisely targets only when no debug session exists
Replace when: 'inDebugMode' with when: 'debugState == stopped' for the CONTINUE keybinding — only fires when actually paused at a breakpoint
Remove the now-unnecessary isEnabled hack from the CONTINUE command
Add a mutex lock _startLock to start() in DebugFrontendApplicationContribution to prevent concurrent invocations during async execution
Immediately update inDebugModeKey and debugStateKey context keys at the synchronous entry point of DebugSessionManager.start() so keybinding when clauses reflect the correct state before any async work begins

How to test

Open any workspace with a Python file (requires debugpy extension)
Add a breakpoint on any line
Press F5 once — confirm debugger starts and pauses at the breakpoint
Hold F5 down for 2-3 seconds
Verify only one debug session exists in the THREADS panel — no additional sessions should spawn
Press F5 once more to continue — confirm the session continues normally and does not start a new session

Follow-ups

The START_NO_DEBUG keybinding (ctrl+f5) still uses when: '!inDebugMode' and could be updated to when: 'debugState == inactive' for consistency — left as a separate follow-up

Breaking changes

This PR introduces breaking changes and requires careful review.

Attribution
N/A
Review checklist

As an author, I have thoroughly tested my changes and carefully followed the review guidelines
User-facing text is internationalized using the nls service (no user-facing text changes in this PR)

This replaces the manual text-entry approach with a keystroke listener in the EditKeybindingDialog, significantly improving UX by capturing real keyboard events.
- Use `debugState == inactive` when clause for START keybinding
  a new session
- Use `debugState == stopped` when clause for CONTINUE keybinding
  instead of `inDebugMode` to only fire when paused at a breakpoint
- Remove hacky `isEnabled` from CONTINUE command that was added in
  PR eclipse-theia#14641 as it is no longer needed with proper when clauses
- Add mutex lock `_startLock` to `start()` method to prevent
  multiple concurrent debug sessions from being spawned by rapid
  key repeat events
- Immediately update `inDebugModeKey` and `debugStateKey` context
  keys at the start of `DebugSessionManager.start()` so keybinding
  when clauses reflect the new state before async session setup

Fixes eclipse-theia#14639
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Waiting on reviewers

Development

Successfully merging this pull request may close these issues.

Key F5 is assigned to 'run' and 'continue' simultaneously

1 participant