[Lldb-commits] [lldb] [lldb-dap] Allow providing debug adapter arguments in the extension (PR #129262)

John Harrison via lldb-commits lldb-commits at lists.llvm.org
Fri Mar 14 15:18:00 PDT 2025


================
@@ -0,0 +1,130 @@
+import * as child_process from "node:child_process";
+import * as vscode from "vscode";
+
+function areArraysEqual<T>(lhs: T[], rhs: T[]): boolean {
+  if (lhs.length !== rhs.length) {
+    return false;
+  }
+  for (let i = 0; i < lhs.length; i++) {
+    if (lhs[i] !== rhs[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+/**
+ * Represents a running lldb-dap process that is accepting connections (i.e. in "server mode").
+ *
+ * Handles startup of the process if it isn't running already as well as prompting the user
+ * to restart when arguments have changed.
+ */
+export class LLDBDapServer implements vscode.Disposable {
+  private serverProcess?: child_process.ChildProcessWithoutNullStreams;
+  private serverInfo?: Promise<{ host: string; port: number }>;
+
+  /**
+   * Starts the server with the provided options. The server will be restarted or reused as
+   * necessary.
+   *
+   * @param dapPath the path to the debug adapter executable
+   * @param args the list of arguments to provide to the debug adapter
+   * @param options the options to provide to the debug adapter process
+   * @returns a promise that resolves with the host and port information or `undefined` if unable to launch the server.
+   */
+  async start(
+    dapPath: string,
+    args: string[],
+    options?: child_process.SpawnOptionsWithoutStdio,
+  ): Promise<{ host: string; port: number } | undefined> {
+    const dapArgs = [...args, "--connection", "connect://localhost:0"];
+    if (!(await this.shouldContinueStartup(dapPath, dapArgs))) {
+      return undefined;
+    }
+
+    if (this.serverInfo) {
+      return this.serverInfo;
+    }
+
+    this.serverInfo = new Promise((resolve, reject) => {
+      const process = child_process.spawn(dapPath, dapArgs, options);
+      process.on("error", (error) => {
+        reject(error);
+        this.serverProcess = undefined;
+        this.serverInfo = undefined;
+      });
+      process.on("exit", (code, signal) => {
+        let errorMessage = "Server process exited early";
+        if (code !== undefined) {
+          errorMessage += ` with code ${code}`;
+        } else if (signal !== undefined) {
+          errorMessage += ` due to signal ${signal}`;
+        }
+        reject(new Error(errorMessage));
+        this.serverProcess = undefined;
+        this.serverInfo = undefined;
+      });
+      process.stdout.setEncoding("utf8").on("data", (data) => {
+        const connection = /connection:\/\/\[([^\]]+)\]:(\d+)/.exec(
+          data.toString(),
+        );
+        if (connection) {
+          const host = connection[1];
+          const port = Number(connection[2]);
+          resolve({ host, port });
+          process.stdout.removeAllListeners();
+        }
+      });
+      this.serverProcess = process;
+    });
+    return this.serverInfo;
+  }
+
+  /**
+   * Checks to see if the server needs to be restarted. If so, it will prompt the user
+   * to ask if they wish to restart.
+   *
+   * @param dapPath the path to the debug adapter
+   * @param args the arguments for the debug adapter
+   * @returns whether or not startup should continue depending on user input
+   */
+  private async shouldContinueStartup(
+    dapPath: string,
+    args: string[],
+  ): Promise<boolean> {
+    if (!this.serverProcess || !this.serverInfo) {
+      return true;
+    }
+
+    if (areArraysEqual(this.serverProcess.spawnargs, [dapPath, ...args])) {
+      return true;
+    }
+
+    const userInput = await vscode.window.showInformationMessage(
+      "A server mode instance of lldb-dap is already running, but the arguments are different from what is requested in your debug configuration or settings. Would you like to restart the server?",
----------------
ashgti wrote:

Should we have a shorter message title and use the detail in the options? e.g. 

```ts
await vscode.window.showInformationMessage(
 'lldb-dap arguments 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.

The previous lldb-dap server was started with:

${this.serverProcess.spawnargs.joined(' ')}

Restarting the server will interrupt any existing debug sessions and start a new server.`
 },
 "Restart",
  "Use Existing",
 )`

https://github.com/llvm/llvm-project/pull/129262


More information about the lldb-commits mailing list