Skip to content

Commit

Permalink
src/goDebugFactory: wait for dlv dap server to start in factory
Browse files Browse the repository at this point in the history
When we start dlv dap, we want to make sure it has started before
sending the info back to vscode so it will be able to connect.
Wait for the 'DAP server listening at' message before returning the
host. Display the error for the user otherwise.

Fixes #1270

Change-Id: Id710b67ceaa87b1f6dff84d8108ac61dfbe15707
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/300071
Trust: Suzy Mueller <[email protected]>
Run-TryBot: Suzy Mueller <[email protected]>
TryBot-Result: kokoro <[email protected]>
Reviewed-by: Hyang-Ah Hana Kim <[email protected]>
  • Loading branch information
suzmue committed Mar 10, 2021
1 parent 7bb2822 commit 3d30385
Showing 1 changed file with 61 additions and 28 deletions.
89 changes: 61 additions & 28 deletions src/goDebugFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,11 @@ export async function startDapServer(
} else {
configuration.port = await getPort();
}
const dlvDapServer = spawnDlvDapServerProcess(configuration);
// Wait to give dlv-dap a chance to start before returning.
return await new Promise<{ port: number; host: string; dlvDapServer: ChildProcessWithoutNullStreams }>((resolve) =>
setTimeout(() => resolve({ port: configuration.port, host: configuration.host, dlvDapServer }), 500)
);
const dlvDapServer = await spawnDlvDapServerProcess(configuration);
return { dlvDapServer, port: configuration.port, host: configuration.host };
}

function spawnDlvDapServerProcess(launchArgs: DebugConfiguration) {
async function spawnDlvDapServerProcess(launchArgs: DebugConfiguration): Promise<ChildProcess> {
const launchArgsEnv = launchArgs.env || {};
const env = Object.assign({}, process.env, launchArgsEnv);

Expand Down Expand Up @@ -114,30 +111,66 @@ function spawnDlvDapServerProcess(launchArgs: DebugConfiguration) {
appendToDebugConsole(`Running: ${dlvPath} ${dlvArgs.join(' ')}`);

const dir = parseProgramArgSync(launchArgs).dirname;
const p = spawn(dlvPath, dlvArgs, {
cwd: dir,
env
});

p.stderr.on('data', (chunk) => {
appendToDebugConsole(chunk.toString());
});
p.stdout.on('data', (chunk) => {
appendToDebugConsole(chunk.toString());
});
p.on('close', (code) => {
if (code) {
appendToDebugConsole(`Process exiting with code: ${code} signal: ${p.killed}`);
} else {
appendToDebugConsole(`Process exited normally: ${p.killed}`);
}
});
p.on('error', (err) => {
if (err) {
appendToDebugConsole(`Error: ${err}`);
}
return await new Promise<ChildProcess>((resolve, reject) => {
const p = spawn(dlvPath, dlvArgs, {
cwd: dir,
env
});
let started = false;
const timeoutToken: NodeJS.Timer = setTimeout(
() => reject(new Error('timed out while waiting for DAP server to start')),
5_000
);

const stopWaitingForServerToStart = (err?: string) => {
clearTimeout(timeoutToken);
started = true;
if (err) {
killProcessTree(p); // We do not need to wait for p to actually be killed.
reject(new Error(err));
} else {
resolve(p);
}
};

p.stdout.on('data', (chunk) => {
if (!started) {
if (chunk.toString().startsWith('DAP server listening at:')) {
stopWaitingForServerToStart();
} else {
stopWaitingForServerToStart(
`Expected 'DAP server listening at:' from debug adapter got '${chunk.toString()}'`
);
}
}
appendToDebugConsole(chunk.toString());
});
p.stderr.on('data', (chunk) => {
if (!started) {
stopWaitingForServerToStart(`Unexpected error from dlv dap on start: '${chunk.toString()}'`);
}
appendToDebugConsole(chunk.toString());
});
p.on('close', (code) => {
if (!started) {
stopWaitingForServerToStart(`dlv dap closed with code: '${code}' signal: ${p.killed}`);
}
if (code) {
appendToDebugConsole(`Process exiting with code: ${code} signal: ${p.killed}`);
} else {
appendToDebugConsole(`Process exited normally: ${p.killed}`);
}
});
p.on('error', (err) => {
if (!started) {
stopWaitingForServerToStart(`Unexpected error from dlv dap on start: '${err}'`);
}
if (err) {
appendToDebugConsole(`Error: ${err}`);
}
});
});
return p;
}

function parseProgramArgSync(
Expand Down

0 comments on commit 3d30385

Please sign in to comment.