Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions extension/configUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as cp from 'child_process';
import * as async from './novsc/async';
import { Dict } from './novsc/commonTypes';
import { expandVariablesInObject } from './novsc/expand';
import { ListenOptions } from 'net';

// Expands variable references of the form ${dbgconfig:name} in all properties of launch configuration.
export function expandDbgConfig(debugConfig: DebugConfiguration, dbgconfigConfig: WorkspaceConfiguration): DebugConfiguration {
Expand Down Expand Up @@ -88,3 +89,4 @@ export async function getLLDBDirectories(executable: string): Promise<LLDBDirect
}
}

export type RpcConfig = ListenOptions & { token?: string };
10 changes: 7 additions & 3 deletions extension/externalLaunch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,13 @@ export class RpcServer {
}

public async listen(options: net.ListenOptions) {
return new Promise<net.AddressInfo | string | null>(resolve =>
this.inner.listen(options, () => resolve(this.inner.address()))
);
return new Promise<net.AddressInfo | string | null>((resolve, reject) => {
try {
this.inner.listen(options, () => resolve(this.inner.address()));
} catch (error) {
reject(error);
}
});
}

public close() {
Expand Down
81 changes: 79 additions & 2 deletions extension/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,52 @@ class Extension implements DebugAdapterDescriptorFactory {
this.rpcServer = undefined;
}
let config = getExtensionConfig();
let options = config.get<any>('rpcServer');
let options = config.get<util.RpcConfig | "auto">('rpcServer');

if (options === "auto") {
// Use an automatically-generated but persistent token. VS Code caches environment contributions between
// reloads, so keeping this static will prevent us from invalidating all terminals on every window reload.
// This helps mostly to prevent other users from accessing the server. A better alternative would probably
// be supporting Unix Sockets - this is what VS Code's Git adapter uses.
let autoToken = this.context.globalState.get<string>("autoRpcToken");
if (!autoToken) {
autoToken = crypto.randomUUID();
await this.context.globalState.update("autoRpcToken", autoToken);
}

options = {
host: "127.0.0.1",
port: 61147, // Just a consistent, random port that's probably not in use.
token: autoToken,
};
}

if (options) {
output.appendLine(`Starting RPC server with: ${inspect(options)}`);

this.rpcServer = new RpcLaunchServer({ token: options.token });
await this.rpcServer.listen(options);
this.rpcServer.onError((err) => {
output.appendLine(`RPC Error: ${inspect(err)}`);
});

let addr;
try {
addr = await this.rpcServer.listen(options);
} catch (err) {
output.appendLine(`Failed to start server: ${inspect(err)}`);
}

// If the user doesn't specify a port, then allow auto-resolution to play out and expose it via environment
// variables.
if (addr && typeof addr == "object") {
options.port = addr.port;
}
}


output.appendLine(`Updating environment contributions for RPC.`);

this.updateEnvironmentVariableCollection(options);
}

// Discover debuggable targets in the current workspace and generate debug configs for them
Expand Down Expand Up @@ -534,4 +574,41 @@ class Extension implements DebugAdapterDescriptorFactory {
}
});
}

/**
* Add bundled binaries like codelldb-launch to $PATH so that users can use them from the terminal without
* manually having to update their rc-files. This is also more resilient across extension versions.
*/
updateEnvironmentVariableCollection(rpcConfig?: util.RpcConfig) {
const binariesUri = Uri.joinPath(this.context.extensionUri, "bin");
const pathContribution = binariesUri.fsPath + path.delimiter;
this.context.environmentVariableCollection.prepend(
"PATH",
pathContribution,
);
this.context.environmentVariableCollection.description =
"Enables use of the `codelldb-launch` program in the terminal";

if (rpcConfig?.host && rpcConfig.port) {
this.context.environmentVariableCollection.replace(
"CODELLDB_LAUNCH_CONNECT",
`${rpcConfig.host}:${rpcConfig.port}`,
);
} else {
this.context.environmentVariableCollection.delete(
"CODELLDB_LAUNCH_CONNECT",
);
}

if (rpcConfig?.token) {
this.context.environmentVariableCollection.replace(
"CODELLDB_LAUNCH_CONFIG",
JSON.stringify({ token: rpcConfig.token }),
);
} else {
this.context.environmentVariableCollection.delete(
"CODELLDB_LAUNCH_CONFIG",
);
}
}
}
15 changes: 12 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -523,9 +523,18 @@
},
"lldb.rpcServer": {
"description": "Start an RPC server that will accept debug configuration requests.",
"type": [
"object",
"null"
"anyOf": [
{
"type": [
"object",
"string",
"null"
]
},
{
"const": "auto",
"description": "Automatically determine connection details and expose them to the integrated terminal."
}
],
"default": null,
"defaultSnippets": [
Expand Down