VS Code Extension ↔ Language Server: Workspace Folder Closure Timing
0 reputation · 21 Feb 2023, 10:44 UTC
0 reputation · 21 Feb 2023, 10:44 UTC
The goal is to understand how the VS Code Extension API’s LanguageClient manages its lifecycle when a workspace folder is closed, compared to when the entire window is reloaded. The documented behavior indicates that the client attempts an automatic restart if the server crashes, but the exact moment when resources are released after a folder closure remains unclear.
Constraints include the fact that the Extension API and the Language Server Protocol (LSP) communicate over JSON‑RPC, typically via stdio or TCP. The behavior may differ between the Desktop client and the Web/Remote versions due to transport limitations. Additionally, memory leaks have been observed when extensions fail to dispose of the LanguageClient instance.
Uncertainty surrounds the cleanup timing: does VS Code dispose of the client immediately upon folder removal, or is disposal deferred until a full window reload? Is there a configuration option to alter this timing, and what triggers the eventual cleanup if the client is not explicitly disposed?
1. Does VS Code dispose of the LanguageClient instance immediately when a workspace folder is closed, or does it wait until the entire window is reloaded?
2. If the client is not disposed, what internal events or conditions trigger the cleanup of its resources?
3. Are there documented settings or API hooks that allow extensions to customize this disposal behavior?
31275 reputation · 21 Feb 2023, 10:58 UTC
VS Code does not automatically dispose of a LanguageClient instance when a workspace folder is closed. The responsibility for managing the client's lifecycle rests entirely with the extension developer. If you do not explicitly call .dispose(), the client remains active in the extension host, and the associated language server process may continue to run in the background until the entire window is reloaded or the extension is deactivated.
Because the LanguageClient is an object managed by the extension host, its cleanup is tied to the extension's lifecycle rather than the workspace's state. The following conditions trigger resource reclamation:
client.dispose() sends the LSP shutdown request followed by an exit notification, ensuring a graceful termination of the server.stdio.In multi-root environments, closing one folder does not necessarily mean the server should be shut down if other folders of the same language are still open. To handle this, extensions should monitor workspace changes rather than relying on automatic disposal.
To customize this behavior, use the vscode.workspace.onDidChangeWorkspaceFolders event to detect when a folder is removed and determine if the server should be disposed of or simply notified to clear its internal cache for that specific path.
To verify if your server is leaking after a folder closure, you can use the following methods:
ps aux | grep [server-name] (Linux/macOS) or Task Manager (Windows) to check if the server process persists after the folder is closed.shutdown handler. If the log does not trigger upon folder closure, the client was not disposed.Diagnostic Requirement: To provide a more specific implementation pattern, please specify if your server uses stdio or TCP transport, as TCP servers are more prone to becoming "zombie" processes if the client is not disposed of correctly.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.