Skip to content

Debug restart recompilation stopped working  #21082

@basvandriel

Description

@basvandriel

Problem Description

The debug restart recompilation feature (implemented in PR #17923, merged Sep 27, 2024) has stopped working. When pressing the restart button (⟳) while debugging Rust tests, the code is no longer recompiled, causing the debugger to use stale binaries even after code changes.

Root Cause

PR #17923 implemented the feature by listening to the onDidTerminateDebugSession event to detect when a debug session was restarting:

vscode.debug.onDidTerminateDebugSession((session) => {
    if (activeDebugSessionIds.includes(session.id)) {
        // Recompile on restart
    }
});

However, VS Code's debug API behavior has changed (likely in a recent VS Code update). The onDidTerminateDebugSession event no longer fires when the restart button is clicked - it only fires when a session is fully terminated/stopped.

Impact

Users who modify code during a debug session and press restart will see:

  • Old variable values in the debugger
  • Outdated code behavior
  • Breakpoints may not align with the actual source
  • Confusing debugging experience requiring manual stop + re-run

Why This Happened

VS Code uses the Debug Adapter Protocol (DAP) for communication between the editor and debug adapters. When restart is triggered:

Before (working):

  1. User clicks restart button
  2. onDidTerminateDebugSession event fires
  3. Extension recompiles
  4. Session restarts with new binary

Now (broken):

  1. User clicks restart button
  2. DAP sends restart command directly to debug adapter
  3. onDidTerminateDebugSession does NOT fire
  4. Session restarts with cached/stale binary

The debug adapter caches the binary and symbols, so even if we tried to recompile asynchronously, the restart would use the old data.

Attempted Solutions

I tested several approaches:

  1. Wait for onDidTerminateDebugSession - No longer fires on restart
  2. Check binary modification time - Debug adapter caches symbols regardless
  3. Send invalidate request to debug adapter - Not supported by all adapters
  4. Intercept DAP restart command - Working solution (PR Fix debug restart to recompile code before restarting #21081)

Solution (PR #21081)

Use DebugAdapterTracker.onWillReceiveMessage to intercept the DAP restart command before it reaches the debug adapter:

vscode.debug.registerDebugAdapterTrackerFactory("*", {
    createDebugAdapterTracker(session) {
        return {
            onWillReceiveMessage: async (message) => {
                if (message.command === "restart") {
                    // Stop session (clears cache)
                    await vscode.debug.stopDebugging(session);
                    // Recompile with progress notification
                    await recompile(session);
                    // Start fresh session
                    await vscode.debug.startDebugging(session.workspaceFolder, session.configuration);
                }
            }
        };
    }
});

The stop → recompile → fresh start sequence is necessary because debug adapters cache binaries/symbols. A simple restart would continue using stale data.

Related Issues

Testing

Reproduced on:

  • VS Code 1.95+
  • CodeLLDB 1.10+
  • rust-analyzer latest

The fix has been tested with:

  • ✅ Single restart after code changes
  • ✅ Multiple consecutive restarts
  • ✅ Error handling for compilation failures
  • ✅ Progress notifications during recompilation
  • ✅ Unit tests for DAP message interception
  • ✅ Integration test documentation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions