[Lldb-commits] [lldb] [vscode-lldb] Restart server when lldb-dap binary has changed (PR #159797)

Roy Shi via lldb-commits lldb-commits at lists.llvm.org
Tue Sep 23 07:16:57 PDT 2025


https://github.com/royitaqi updated https://github.com/llvm/llvm-project/pull/159797

>From e4d4d1c8d38ae929081778b47859c47a5a5665c8 Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Fri, 19 Sep 2025 07:57:06 -0700
Subject: [PATCH 1/4] [vscode-lldb] Restart server when the lldb-dap binary has
 changed

---
 lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts | 77 +++++++++++++++----
 1 file changed, 64 insertions(+), 13 deletions(-)

diff --git a/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts b/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
index 774be50053a17..7a1754f4bce6a 100644
--- a/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
+++ b/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
@@ -1,4 +1,5 @@
 import * as child_process from "node:child_process";
+import * as path from "path";
 import { isDeepStrictEqual } from "util";
 import * as vscode from "vscode";
 
@@ -12,6 +13,10 @@ export class LLDBDapServer implements vscode.Disposable {
   private serverProcess?: child_process.ChildProcessWithoutNullStreams;
   private serverInfo?: Promise<{ host: string; port: number }>;
   private serverSpawnInfo?: string[];
+  // Detects changes to the lldb-dap executable file since the server's startup.
+  private serverFileWatcher?: vscode.FileSystemWatcher;
+  // Indicates whether the lldb-dap executable file has changed since the server's startup.
+  private serverFileChanged?: boolean;
 
   constructor() {
     vscode.commands.registerCommand(
@@ -83,6 +88,18 @@ export class LLDBDapServer implements vscode.Disposable {
       });
       this.serverProcess = process;
       this.serverSpawnInfo = this.getSpawnInfo(dapPath, dapArgs, options?.env);
+      this.serverFileChanged = false;
+      // Cannot do `createFileSystemWatcher(dapPath)` for a single file. Have to use `RelativePattern`.
+      // See https://github.com/microsoft/vscode/issues/141011#issuecomment-1016772527
+      this.serverFileWatcher = vscode.workspace.createFileSystemWatcher(
+        new vscode.RelativePattern(
+          vscode.Uri.file(path.dirname(dapPath)),
+          path.basename(dapPath),
+        ),
+      );
+      this.serverFileWatcher.onDidChange(() => {
+        this.serverFileChanged = true;
+      });
     });
     return this.serverInfo;
   }
@@ -100,20 +117,34 @@ export class LLDBDapServer implements vscode.Disposable {
     args: string[],
     env: NodeJS.ProcessEnv | { [key: string]: string } | undefined,
   ): Promise<boolean> {
-    if (!this.serverProcess || !this.serverInfo || !this.serverSpawnInfo) {
+    if (
+      !this.serverProcess ||
+      !this.serverInfo ||
+      !this.serverSpawnInfo ||
+      !this.serverFileWatcher ||
+      this.serverFileChanged === undefined
+    ) {
       return true;
     }
 
-    const newSpawnInfo = this.getSpawnInfo(dapPath, args, env);
-    if (isDeepStrictEqual(this.serverSpawnInfo, newSpawnInfo)) {
-      return true;
-    }
+    // Check if the server has changed. If so, generate message and detail for user prompt.
+    const messageAndDetail = (() => {
+      if (this.serverFileChanged) {
+        return {
+          message:
+            "The lldb-dap binary has changed. Would you like to restart the server?",
+          detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with an old binary.
 
-    const userInput = await vscode.window.showInformationMessage(
-      "The arguments to lldb-dap have changed. Would you like to restart the server?",
-      {
-        modal: true,
-        detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with different arguments.
+Restarting the server will interrupt any existing debug sessions and start a new server.`,
+        };
+      }
+
+      const newSpawnInfo = this.getSpawnInfo(dapPath, args, env);
+      if (!isDeepStrictEqual(this.serverSpawnInfo, newSpawnInfo)) {
+        return {
+          message:
+            "The arguments to lldb-dap have changed. Would you like to restart the server?",
+          detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with different arguments.
 
 The previous lldb-dap server was started with:
 
@@ -124,15 +155,31 @@ The new lldb-dap server will be started with:
 ${newSpawnInfo.join(" ")}
 
 Restarting the server will interrupt any existing debug sessions and start a new server.`,
+        };
+      }
+
+      return null;
+    })();
+
+    // If the server hasn't changed, continue startup without killing it.
+    if (messageAndDetail === null) {
+      return true;
+    }
+
+    // The server has changed. Prompt the user to restart it.
+    const { message, detail } = messageAndDetail;
+    const userInput = await vscode.window.showInformationMessage(
+      message,
+      {
+        modal: true,
+        detail,
       },
       "Restart",
       "Use Existing",
     );
     switch (userInput) {
       case "Restart":
-        this.serverProcess.kill();
-        this.serverProcess = undefined;
-        this.serverInfo = undefined;
+        this.dispose();
         return true;
       case "Use Existing":
         return true;
@@ -156,6 +203,10 @@ Restarting the server will interrupt any existing debug sessions and start a new
     if (this.serverProcess === process) {
       this.serverProcess = undefined;
       this.serverInfo = undefined;
+      this.serverSpawnInfo = undefined;
+      this.serverFileWatcher?.dispose();
+      this.serverFileWatcher = undefined;
+      this.serverFileChanged = undefined;
     }
   }
 

>From eeae07535707f5dae0518f66b4f24382fa608874 Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Fri, 19 Sep 2025 15:00:41 -0700
Subject: [PATCH 2/4] Use chokidar instead

---
 lldb/tools/lldb-dap/package-lock.json         | 31 +++++++++++++++++++
 lldb/tools/lldb-dap/package.json              |  3 ++
 lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts | 18 +++++------
 3 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/lldb/tools/lldb-dap/package-lock.json b/lldb/tools/lldb-dap/package-lock.json
index 26db1ce6df2fd..3d8907f3115f6 100644
--- a/lldb/tools/lldb-dap/package-lock.json
+++ b/lldb/tools/lldb-dap/package-lock.json
@@ -8,6 +8,9 @@
       "name": "lldb-dap",
       "version": "0.2.16",
       "license": "Apache 2.0 License with LLVM exceptions",
+      "dependencies": {
+        "chokidar": "^4.0.3"
+      },
       "devDependencies": {
         "@types/node": "^18.19.41",
         "@types/tabulator-tables": "^6.2.10",
@@ -1301,6 +1304,21 @@
         "url": "https://github.com/sponsors/fb55"
       }
     },
+    "node_modules/chokidar": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+      "license": "MIT",
+      "dependencies": {
+        "readdirp": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 14.16.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
     "node_modules/chownr": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
@@ -2712,6 +2730,19 @@
         "node": ">= 6"
       }
     },
+    "node_modules/readdirp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 14.18.0"
+      },
+      "funding": {
+        "type": "individual",
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
     "node_modules/safe-buffer": {
       "version": "5.2.1",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index 6566ba3bdee13..3892535853f56 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -27,6 +27,9 @@
   "categories": [
     "Debuggers"
   ],
+  "dependencies": {
+    "chokidar": "^4.0.3"
+  },
   "devDependencies": {
     "@types/node": "^18.19.41",
     "@types/tabulator-tables": "^6.2.10",
diff --git a/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts b/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
index 7a1754f4bce6a..f38093e935a42 100644
--- a/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
+++ b/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
@@ -1,3 +1,4 @@
+import { FSWatcher, watch as chokidarWatch } from 'chokidar';
 import * as child_process from "node:child_process";
 import * as path from "path";
 import { isDeepStrictEqual } from "util";
@@ -14,7 +15,7 @@ export class LLDBDapServer implements vscode.Disposable {
   private serverInfo?: Promise<{ host: string; port: number }>;
   private serverSpawnInfo?: string[];
   // Detects changes to the lldb-dap executable file since the server's startup.
-  private serverFileWatcher?: vscode.FileSystemWatcher;
+  private serverFileWatcher?: FSWatcher;
   // Indicates whether the lldb-dap executable file has changed since the server's startup.
   private serverFileChanged?: boolean;
 
@@ -91,15 +92,10 @@ export class LLDBDapServer implements vscode.Disposable {
       this.serverFileChanged = false;
       // Cannot do `createFileSystemWatcher(dapPath)` for a single file. Have to use `RelativePattern`.
       // See https://github.com/microsoft/vscode/issues/141011#issuecomment-1016772527
-      this.serverFileWatcher = vscode.workspace.createFileSystemWatcher(
-        new vscode.RelativePattern(
-          vscode.Uri.file(path.dirname(dapPath)),
-          path.basename(dapPath),
-        ),
-      );
-      this.serverFileWatcher.onDidChange(() => {
-        this.serverFileChanged = true;
-      });
+      this.serverFileWatcher = chokidarWatch(dapPath);
+      this.serverFileWatcher
+        .on('change', () => this.serverFileChanged = true)
+        .on('unlink', () => this.serverFileChanged = true);
     });
     return this.serverInfo;
   }
@@ -204,7 +200,7 @@ Restarting the server will interrupt any existing debug sessions and start a new
       this.serverProcess = undefined;
       this.serverInfo = undefined;
       this.serverSpawnInfo = undefined;
-      this.serverFileWatcher?.dispose();
+      this.serverFileWatcher?.close();
       this.serverFileWatcher = undefined;
       this.serverFileChanged = undefined;
     }

>From 2b6e28817043a33c284f394b26d48885735ac9d3 Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Fri, 19 Sep 2025 15:28:21 -0700
Subject: [PATCH 3/4] Show both the binary change and the arguments change in
 the same dialog box

---
 lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts | 45 +++++++------------
 1 file changed, 17 insertions(+), 28 deletions(-)

diff --git a/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts b/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
index f38093e935a42..b8b5bb628a787 100644
--- a/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
+++ b/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
@@ -123,25 +123,17 @@ export class LLDBDapServer implements vscode.Disposable {
       return true;
     }
 
-    // Check if the server has changed. If so, generate message and detail for user prompt.
-    const messageAndDetail = (() => {
-      if (this.serverFileChanged) {
-        return {
-          message:
-            "The lldb-dap binary has changed. Would you like to restart the server?",
-          detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with an old binary.
+    const changeTLDR = [];
+    const changeDetails = [];
 
-Restarting the server will interrupt any existing debug sessions and start a new server.`,
-        };
-      }
-
-      const newSpawnInfo = this.getSpawnInfo(dapPath, args, env);
-      if (!isDeepStrictEqual(this.serverSpawnInfo, newSpawnInfo)) {
-        return {
-          message:
-            "The arguments to lldb-dap have changed. Would you like to restart the server?",
-          detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with different arguments.
+    if (this.serverFileChanged) {
+      changeTLDR.push("an old binary");
+    }
 
+    const newSpawnInfo = this.getSpawnInfo(dapPath, args, env);
+    if (!isDeepStrictEqual(this.serverSpawnInfo, newSpawnInfo)) {
+      changeTLDR.push("different arguments");
+      changeDetails.push(`
 The previous lldb-dap server was started with:
 
 ${this.serverSpawnInfo.join(" ")}
@@ -149,26 +141,23 @@ ${this.serverSpawnInfo.join(" ")}
 The new lldb-dap server will be started with:
 
 ${newSpawnInfo.join(" ")}
-
-Restarting the server will interrupt any existing debug sessions and start a new server.`,
-        };
-      }
-
-      return null;
-    })();
+`
+      );
+    }
 
     // If the server hasn't changed, continue startup without killing it.
-    if (messageAndDetail === null) {
+    if (changeTLDR.length === 0) {
       return true;
     }
 
     // The server has changed. Prompt the user to restart it.
-    const { message, detail } = messageAndDetail;
     const userInput = await vscode.window.showInformationMessage(
-      message,
+      "The lldb-dap server has changed. Would you like to restart the server?",
       {
         modal: true,
-        detail,
+        detail: `An existing lldb-dap server (${this.serverProcess.pid}) is running with ${changeTLDR.map(s => `*${s}*`).join(" and ")}.
+${changeDetails.join("\n")}
+Restarting the server will interrupt any existing debug sessions and start a new server.`,
       },
       "Restart",
       "Use Existing",

>From de3c385d557b4a3ffc916438c8f91a73755b0604 Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Tue, 23 Sep 2025 07:14:20 -0700
Subject: [PATCH 4/4] Remove out-dated inline comments

---
 lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts b/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
index c6ae3b3ef73a3..4e348965930d9 100644
--- a/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
+++ b/lldb/tools/lldb-dap/src-ts/lldb-dap-server.ts
@@ -90,8 +90,6 @@ export class LLDBDapServer implements vscode.Disposable {
       this.serverProcess = process;
       this.serverSpawnInfo = this.getSpawnInfo(dapPath, dapArgs, options?.env);
       this.serverFileChanged = false;
-      // Cannot do `createFileSystemWatcher(dapPath)` for a single file. Have to use `RelativePattern`.
-      // See https://github.com/microsoft/vscode/issues/141011#issuecomment-1016772527
       this.serverFileWatcher = chokidarWatch(dapPath);
       this.serverFileWatcher
         .on('change', () => this.serverFileChanged = true)



More information about the lldb-commits mailing list