microsoft / vscode-debugadapter-node

Debug adapter protocol and implementation for VS Code.
Other
271 stars 77 forks source link

DebugAdapterNamedPipeServer does not seem to read from the pipe unless a request has been sent recently #279

Closed miskeletor closed 1 year ago

miskeletor commented 1 year ago

It seems like the pipe is not read until a request is sent from the editor. I'm trying to get vscode to stop at a breakpoint with the "stopped" event. The event is not read from the pipe, according to vscode.DebugAdapterTracker, unless I trigger the editor to send a request.

roblourens commented 1 year ago

Can you include some code that demonstrates the issue?

miskeletor commented 1 year ago

Here is the extension.ts

import * as vscode from 'vscode';

import { ContraptionDebugAdapterTracker } from './contraptionDebug';

export function activate(context: vscode.ExtensionContext) {
    context.subscriptions.push(vscode.commands.registerCommand('contraption-debug.startDebug', () => {
        vscode.window.showInformationMessage('Starting debugger!');
        vscode.debug.startDebugging(undefined, {
            type: 'contraption',
            name: 'Attach',
            request: 'attach'
        });
    }));

    context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('contraption', new ContraptionDebugAdapterDescriptorFactory()));
    context.subscriptions.push(vscode.debug.registerDebugAdapterTrackerFactory('contraption', new ContraptionDebugAdapterTrackerFactory()));
}

export function deactivate() {}

class ContraptionDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
    createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
        return new vscode.DebugAdapterNamedPipeServer("\\\\.\\pipe\\ContraptionDebugServer");
    }
    dispose() {}
}

class ContraptionDebugAdapterTrackerFactory implements vscode.DebugAdapterTrackerFactory {
    createDebugAdapterTracker(session: vscode.DebugSession): vscode.ProviderResult<vscode.DebugAdapterTracker> {
        return new ContraptionDebugAdapterTracker(session);
    }
    dispose() {}
}

The setting up works etc, but as soon as the debug adapter (game) sends something that is not in response to a request. It isn't received on the other end. For example, this event is not received until I do something like putting a new breakpoint: {"body":{"description":"breakpoint at C:/code/ScrapMechanic_2/Data/Scripts/game/BasePlayer.lua:589","hitBreakpointIds":[1],"id":1,"reason":"breakpoint","threadId":1},"event":"stopped","seq":7,"type":"event"}

The game runs 2 background threads, 1 for receiving and responding to requests and 1 that sends events.

miskeletor commented 1 year ago

Am I just doing something wrong here?

connor4312 commented 1 year ago

Can you share how you're setting up the named pipe on the debug adapter side?

miskeletor commented 1 year ago

The message was never actually sent from my side. Some bad logging 😅. The ReadFile operation on one thread was blocking the WriteFile on the other thread. Rewrote it to use async I/O (overlapped) on only 1 thread and got it working.