-
Couldn't load subscription status.
- Fork 122
Configurable startup timeout for supervisor; better exit detection #10042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -289,6 +289,7 @@ export class KCApi implements PositronSupervisorApi { | |
| // Consult configuration to see if we should show this terminal | ||
| const config = vscode.workspace.getConfiguration('kernelSupervisor'); | ||
| const showTerminal = config.get<boolean>('showTerminal', false); | ||
| const startupTimeout = config.get<number>('startupTimeout', 10) * 1000; | ||
|
|
||
| // Create a temporary file with a random name to use for logs | ||
| const logFile = path.join(os.tmpdir(), `kallichore-${sessionId}.log`); | ||
|
|
@@ -367,25 +368,11 @@ export class KCApi implements PositronSupervisorApi { | |
| } | ||
| } | ||
|
|
||
| // Start the server in a new terminal | ||
| this.log(`Starting Kallichore server ${shellPath} with connection file ${connectionFile}`); | ||
| const terminal = vscode.window.createTerminal({ | ||
| name: 'Kallichore', | ||
| shellPath: wrapperPath, | ||
| shellArgs, | ||
| message: `*** Kallichore Server (${shellPath}) ***`, | ||
| hideFromUser: !showTerminal, | ||
| isTransient: false | ||
| } satisfies vscode.TerminalOptions); | ||
|
|
||
| // Flag to track if the terminal exited before the start barrier opened | ||
| let exited = false; | ||
|
|
||
| // Listen for the terminal to close. If it closes unexpectedly before | ||
| // the start barrier opens, provide some feedback. | ||
| const closeListener = vscode.window.onDidCloseTerminal(async (closedTerminal) => { | ||
| // Ignore closed terminals that aren't the one we started | ||
| if (closedTerminal !== terminal) { | ||
| if (closedTerminal !== this._terminal) { | ||
| return; | ||
| } | ||
|
|
||
|
|
@@ -405,8 +392,8 @@ export class KCApi implements PositronSupervisorApi { | |
|
|
||
| // Read the contents of the output file and log it | ||
| const contents = fs.readFileSync(outFile, 'utf8'); | ||
| if (terminal.exitStatus && terminal.exitStatus.code) { | ||
| this.log(`Supervisor terminal closed with exit code ${terminal.exitStatus.code}; output:\n${contents}`); | ||
| if (this._terminal.exitStatus && this._terminal.exitStatus.code) { | ||
| this.log(`Supervisor terminal closed with exit code ${this._terminal.exitStatus.code}; output:\n${contents}`); | ||
| } else { | ||
| this.log(`Supervisor terminal closed unexpectedly; output:\n${contents}`); | ||
| } | ||
|
|
@@ -424,6 +411,21 @@ export class KCApi implements PositronSupervisorApi { | |
| } | ||
| }); | ||
|
|
||
|
|
||
| // Start the server in a new terminal | ||
| this.log(`Starting Kallichore server ${shellPath} with connection file ${connectionFile}`); | ||
| this._terminal = vscode.window.createTerminal({ | ||
| name: 'Kallichore', | ||
| shellPath: wrapperPath, | ||
| shellArgs, | ||
| message: `*** Kallichore Server (${shellPath}) ***`, | ||
| hideFromUser: !showTerminal, | ||
| isTransient: false | ||
| } satisfies vscode.TerminalOptions); | ||
|
|
||
| // Flag to track if the terminal exited before the start barrier opened | ||
| let exited = false; | ||
|
|
||
| // Ensure this listener is disposed when the API is disposed | ||
| this._disposables.push(closeListener); | ||
|
|
||
|
|
@@ -437,7 +439,7 @@ export class KCApi implements PositronSupervisorApi { | |
| })); | ||
|
|
||
| // Wait for the terminal to start and get the PID | ||
| let processId = await terminal.processId; | ||
| let processId = await this._terminal.processId; | ||
|
|
||
| // Wait for the connection file to be written by the server | ||
| let connectionData: KallichoreServerState | undefined = undefined; | ||
|
|
@@ -481,6 +483,16 @@ export class KCApi implements PositronSupervisorApi { | |
| this.log(`Error reading connection file (attempt ${retry}): ${err}`); | ||
| } | ||
|
|
||
| // Every 10 retries, check to see if the server process has exited. | ||
| if (!exited && processId && retry % 10 === 0) { | ||
| try { | ||
| process.kill(processId, 0); | ||
| } catch (err) { | ||
| this.log(`Kallichore server PID ${processId} is not running`); | ||
| exited = true; | ||
| } | ||
| } | ||
|
|
||
| // Has the terminal exited? if it has, there's no point in continuing to retry. | ||
| if (exited) { | ||
| let message = `The supervisor process exited unexpectedly during startup`; | ||
|
|
@@ -497,7 +509,7 @@ export class KCApi implements PositronSupervisorApi { | |
| } | ||
|
|
||
| const elapsed = Date.now() - startTime; | ||
| if (elapsed > 10000) { | ||
| if (elapsed > startupTimeout) { | ||
| let message = `Connection file was not created after ${elapsed}ms`; | ||
|
|
||
| // Include any output from the server process to help diagnose the problem | ||
|
|
@@ -574,7 +586,7 @@ export class KCApi implements PositronSupervisorApi { | |
| // trying up to 10 seconds from the time we got a process ID | ||
|
||
| // established. | ||
| if (err.code === 'ECONNREFUSED' || err.code === 'ENOENT') { | ||
| if (elapsed < 10000) { | ||
| if (elapsed < startupTimeout) { | ||
| // Log every few attempts. We don't want to overwhelm | ||
| // the logs, and it's normal for us to encounter a few | ||
| // connection refusals before the server is ready. | ||
|
|
@@ -609,7 +621,7 @@ export class KCApi implements PositronSupervisorApi { | |
| // If the request times out, go ahead and try again as long as | ||
| // it hasn't been more than 10 seconds since we started. This | ||
| // can happen if the server is slow to start. | ||
| if (err.code === 'ETIMEDOUT' && elapsed < 10000) { | ||
| if (err.code === 'ETIMEDOUT' && elapsed < startupTimeout) { | ||
| this.log(`Request for server status timed out; retrying (attempt ${retry + 1}, ${elapsed}ms)`); | ||
| continue; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be useful to log these config settings to the output pane?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! Done in 96ec61f.