Skip to content

Commit af09df7

Browse files
authored
Merge pull request #6399 from dibarbet/pipe_timeout_option
Show error when process fails to start
2 parents 8b0aa39 + cd0aa38 commit af09df7

File tree

4 files changed

+32
-4
lines changed

4 files changed

+32
-4
lines changed

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,12 @@
11301130
"scope": "machine-overridable",
11311131
"description": "%configuration.dotnet.server.path%"
11321132
},
1133+
"dotnet.server.startTimeout": {
1134+
"type": "number",
1135+
"scope": "machine-overridable",
1136+
"default": 30000,
1137+
"description": "%configuration.dotnet.server.startTimeout%"
1138+
},
11331139
"dotnet.server.waitForDebugger": {
11341140
"type": "boolean",
11351141
"scope": "machine-overridable",

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"configuration.dotnet.defaultSolution.description": "The path of the default solution to be opened in the workspace, or set to 'disable' to skip it. (Previously `omnisharp.defaultLaunchSolution`)",
33
"configuration.dotnet.dotnetPath": "Specifies the path to a dotnet installation directory to use instead of the default system one. This only influences the dotnet installation to use for hosting the language server itself. Example: \"/home/username/mycustomdotnetdirectory\".",
44
"configuration.dotnet.server.path": "Specifies the absolute path to the server (LSP or O#) executable. When left empty the version pinned to the C# Extension is used. (Previously `omnisharp.path`)",
5+
"configuration.dotnet.server.startTimeout": "Specifies a timeout (in ms) for the client to successfully start and connect to the language server.",
56
"configuration.dotnet.server.waitForDebugger": "Passes the --debug flag when launching the server to allow a debugger to be attached. (Previously `omnisharp.waitForDebugger`)",
67
"configuration.dotnet.server.trace": "Sets the logging level for the language server",
78
"configuration.dotnet.server.extensionPaths": "Override for path to language server --extension arguments",

src/lsptoolshost/roslynLanguageServer.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,28 @@ export class RoslynLanguageServer {
532532
childProcess = cp.spawn(serverPath, args, cpOptions);
533533
}
534534

535+
// Record the stdout and stderr streams from the server process.
536+
childProcess.stdout.on('data', (data: { toString: (arg0: any) => any }) => {
537+
const result: string = isString(data) ? data : data.toString(RoslynLanguageServer.encoding);
538+
_channel.append('[stdout] ' + result);
539+
});
540+
childProcess.stderr.on('data', (data: { toString: (arg0: any) => any }) => {
541+
const result: string = isString(data) ? data : data.toString(RoslynLanguageServer.encoding);
542+
_channel.append('[stderr] ' + result);
543+
});
544+
535545
// Timeout promise used to time out the connection process if it takes too long.
536-
const timeout = new Promise<undefined>((resolve) => {
537-
RAL().timer.setTimeout(resolve, 30000);
546+
const timeout = new Promise<undefined>((resolve, reject) => {
547+
RAL().timer.setTimeout(resolve, languageServerOptions.startTimeout);
548+
549+
// If the child process exited unexpectedly, reject the promise early.
550+
// Error information will be captured from the stdout/stderr streams above.
551+
childProcess.on('exit', (code) => {
552+
if (code && code !== 0) {
553+
_channel.appendLine(`Language server process exited with ${code}`);
554+
reject();
555+
}
556+
});
538557
});
539558

540559
// The server process will create the named pipe used for communcation. Wait for it to be created,
@@ -543,8 +562,6 @@ export class RoslynLanguageServer {
543562
_channel.appendLine('waiting for named pipe information from server...');
544563
childProcess.stdout.on('data', (data: { toString: (arg0: any) => any }) => {
545564
const result: string = isString(data) ? data : data.toString(RoslynLanguageServer.encoding);
546-
_channel.append('[stdout] ' + result);
547-
548565
// Use the regular expression to find all JSON lines
549566
const jsonLines = result.match(RoslynLanguageServer.namedPipeKeyRegex);
550567
if (jsonLines) {

src/shared/options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export interface LanguageServerOptions {
7272
readonly logLevel: string;
7373
readonly documentSelector: DocumentSelector;
7474
readonly extensionsPaths: string[] | null;
75+
readonly startTimeout: number;
7576
}
7677

7778
export interface RazorOptions {
@@ -377,6 +378,9 @@ class LanguageServerOptionsImpl implements LanguageServerOptions {
377378
public get extensionsPaths() {
378379
return readOption<string[] | null>('dotnet.server.extensionPaths', null);
379380
}
381+
public get startTimeout() {
382+
return readOption<number>('dotnet.server.startTimeout', 30000);
383+
}
380384
}
381385

382386
class RazorOptionsImpl implements RazorOptions {

0 commit comments

Comments
 (0)