🐛 Stop the LSP shutdown context-canceled log
The TS 7 Go server races Session.updateWatches against the exit notification; handleExit returns io.EOF, the background context is cancelled, and the bare error is flushed to stderr once the outgoing queue closes (server.go / logger.go). Send shutdown and close stdin instead: EOF makes the server exit cleanly (code 0, no output), with the kill kept as a fallback. testing.md records the cause.
This commit is contained in:
1 parent
13497d1df8
commit
8b73143740
2 files changed
+24
-16
No files matched your search
@@ -165,10 +165,13 @@ transport and protocol plumbing are not hand-rolled (see
|
|||||||
any order; the file is an integration test (~1.6 s) that needs `node_modules`.
|
any order; the file is an integration test (~1.6 s) that needs `node_modules`.
|
||||||
`didOpen` is handled in order before the completion request, so no settle
|
`didOpen` is handled in order before the completion request, so no settle
|
||||||
delay is needed.
|
delay is needed.
|
||||||
- The Go server logs `context canceled` on stderr once per server as it shuts
|
- The TS 7 Go server has a shutdown race: `handleExit` returns `io.EOF`, which
|
||||||
down (nine lines per `test:unit` run). It is benign and predates the protocol
|
cancels the background context while `Session.updateWatches` is still running
|
||||||
client — the hand-rolled client produced the same line — so it is left as is
|
(`internal/project/session.go`), so the bare `context canceled` error is
|
||||||
rather than filtered out of the server's stderr.
|
flushed straight to stderr once the outgoing queue is closed, and the server
|
||||||
|
exits 1 even though LSP expects 0 after `shutdown`. The helper therefore sends
|
||||||
|
`shutdown` and then closes stdin instead of sending `exit`; EOF makes the
|
||||||
|
server exit cleanly (code 0, no output), and the kill is kept as a fallback.
|
||||||
|
|
||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
ConfigurationRequest,
|
ConfigurationRequest,
|
||||||
createMessageConnection,
|
createMessageConnection,
|
||||||
DidOpenTextDocumentNotification,
|
DidOpenTextDocumentNotification,
|
||||||
ExitNotification,
|
|
||||||
InitializedNotification,
|
InitializedNotification,
|
||||||
InitializeRequest,
|
InitializeRequest,
|
||||||
type MessageConnection,
|
type MessageConnection,
|
||||||
@@ -140,18 +139,24 @@ export class LspSession {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** `shutdown` + `exit`, then kill the server; safe after a failed probe. */
|
/** `shutdown` + close stdin, then kill the server; safe after a failed probe. */
|
||||||
public close(): Promise<void> {
|
public close(): Promise<void> {
|
||||||
return this.#connection
|
return (
|
||||||
.sendRequest(ShutdownRequest.type)
|
this.#connection
|
||||||
.then(() =>
|
.sendRequest(ShutdownRequest.type)
|
||||||
this.#connection.sendNotification(ExitNotification.type),
|
// The TS 7 Go server races a background task against the `exit`
|
||||||
)
|
// notification and logs a bare `context canceled` to stderr as it
|
||||||
.then(() => delay(EXIT_DELAY_MS))
|
// tears down (see development/testing.md § Autocomplete). EOF on
|
||||||
.finally(() => {
|
// stdin shuts it down cleanly instead: exit 0, no output.
|
||||||
this.#connection.dispose();
|
.then(() => {
|
||||||
this.#child.kill();
|
this.#child.stdin.end();
|
||||||
});
|
})
|
||||||
|
.then(() => delay(EXIT_DELAY_MS))
|
||||||
|
.finally(() => {
|
||||||
|
this.#connection.dispose();
|
||||||
|
this.#child.kill();
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ensureInitialized(): Promise<void> {
|
#ensureInitialized(): Promise<void> {
|
||||||
|
|||||||
Reference in new issue
Block a user