Skip to content

Commit e4d4d1c

Browse files
committed
[vscode-lldb] Restart server when the lldb-dap binary has changed
1 parent f1ba44f commit e4d4d1c

File tree

1 file changed

+64
-13
lines changed

1 file changed

+64
-13
lines changed

lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as child_process from "node:child_process";
2+
import * as path from "path";
23
import { isDeepStrictEqual } from "util";
34
import * as vscode from "vscode";
45

@@ -12,6 +13,10 @@ export class LLDBDapServer implements vscode.Disposable {
1213
private serverProcess?: child_process.ChildProcessWithoutNullStreams;
1314
private serverInfo?: Promise<{ host: string; port: number }>;
1415
private serverSpawnInfo?: string[];
16+
// Detects changes to the lldb-dap executable file since the server's startup.
17+
private serverFileWatcher?: vscode.FileSystemWatcher;
18+
// Indicates whether the lldb-dap executable file has changed since the server's startup.
19+
private serverFileChanged?: boolean;
1520

1621
constructor() {
1722
vscode.commands.registerCommand(
@@ -83,6 +88,18 @@ export class LLDBDapServer implements vscode.Disposable {
8388
});
8489
this.serverProcess = process;
8590
this.serverSpawnInfo = this.getSpawnInfo(dapPath, dapArgs, options?.env);
91+
this.serverFileChanged = false;
92+
// Cannot do `createFileSystemWatcher(dapPath)` for a single file. Have to use `RelativePattern`.
93+
// See https://github.com/microsoft/vscode/issues/141011#issuecomment-1016772527
94+
this.serverFileWatcher = vscode.workspace.createFileSystemWatcher(
95+
new vscode.RelativePattern(
96+
vscode.Uri.file(path.dirname(dapPath)),
97+
path.basename(dapPath),
98+
),
99+
);
100+
this.serverFileWatcher.onDidChange(() => {
101+
this.serverFileChanged = true;
102+
});
86103
});
87104
return this.serverInfo;
88105
}
@@ -100,20 +117,34 @@ export class LLDBDapServer implements vscode.Disposable {
100117
args: string[],
101118
env: NodeJS.ProcessEnv | { [key: string]: string } | undefined,
102119
): Promise<boolean> {
103-
if (!this.serverProcess || !this.serverInfo || !this.serverSpawnInfo) {
120+
if (
121+
!this.serverProcess ||
122+
!this.serverInfo ||
123+
!this.serverSpawnInfo ||
124+
!this.serverFileWatcher ||
125+
this.serverFileChanged === undefined
126+
) {
104127
return true;
105128
}
106129

107-
const newSpawnInfo = this.getSpawnInfo(dapPath, args, env);
108-
if (isDeepStrictEqual(this.serverSpawnInfo, newSpawnInfo)) {
109-
return true;
110-
}
130+
// Check if the server has changed. If so, generate message and detail for user prompt.
131+
const messageAndDetail = (() => {
132+
if (this.serverFileChanged) {
133+
return {
134+
message:
135+
"The lldb-dap binary has changed. Would you like to restart the server?",
136+
detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with an old binary.
111137
112-
const userInput = await vscode.window.showInformationMessage(
113-
"The arguments to lldb-dap have changed. Would you like to restart the server?",
114-
{
115-
modal: true,
116-
detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with different arguments.
138+
Restarting the server will interrupt any existing debug sessions and start a new server.`,
139+
};
140+
}
141+
142+
const newSpawnInfo = this.getSpawnInfo(dapPath, args, env);
143+
if (!isDeepStrictEqual(this.serverSpawnInfo, newSpawnInfo)) {
144+
return {
145+
message:
146+
"The arguments to lldb-dap have changed. Would you like to restart the server?",
147+
detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with different arguments.
117148
118149
The previous lldb-dap server was started with:
119150
@@ -124,15 +155,31 @@ The new lldb-dap server will be started with:
124155
${newSpawnInfo.join(" ")}
125156
126157
Restarting the server will interrupt any existing debug sessions and start a new server.`,
158+
};
159+
}
160+
161+
return null;
162+
})();
163+
164+
// If the server hasn't changed, continue startup without killing it.
165+
if (messageAndDetail === null) {
166+
return true;
167+
}
168+
169+
// The server has changed. Prompt the user to restart it.
170+
const { message, detail } = messageAndDetail;
171+
const userInput = await vscode.window.showInformationMessage(
172+
message,
173+
{
174+
modal: true,
175+
detail,
127176
},
128177
"Restart",
129178
"Use Existing",
130179
);
131180
switch (userInput) {
132181
case "Restart":
133-
this.serverProcess.kill();
134-
this.serverProcess = undefined;
135-
this.serverInfo = undefined;
182+
this.dispose();
136183
return true;
137184
case "Use Existing":
138185
return true;
@@ -156,6 +203,10 @@ Restarting the server will interrupt any existing debug sessions and start a new
156203
if (this.serverProcess === process) {
157204
this.serverProcess = undefined;
158205
this.serverInfo = undefined;
206+
this.serverSpawnInfo = undefined;
207+
this.serverFileWatcher?.dispose();
208+
this.serverFileWatcher = undefined;
209+
this.serverFileChanged = undefined;
159210
}
160211
}
161212

0 commit comments

Comments
 (0)