redhat-developer / redhat-developer/lsp4ij
Ongoing futures never complete when LSP server crashes
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 344
- Forks
- 113
- Avg merge
- 5h 22m
- Merged PRs (30d)
- 15
Description
When the LSP server crashes or terminates unexpectedly, the ongoing futures for pending requests (such as Hover, Completion, Diagnostics, etc.) are never explicitly cancelled by LSP4IJ and can hang indefinitely (never completing).
Here is a detailed breakdown of the codebase research confirming this behavior and explaining why it happens:
1. Ongoing Futures are Owned by LSPFileSupport (Persisting on PsiFile)
- Ongoing request futures (e.g.,
LSPCompletionSupport,LSPHoverSupport) are managed by subclasses ofAbstractLSPFeatureSupportwhich are held byLSPFileSupport(LSPFileSupport.java). LSPFileSupportis attached as user data to each openPsiFile(file.putUserData(LSP_FILE_SUPPORT_KEY, this)).- It is registered with the Project Disposer:
This means the feature supports and their cached futures are only disposed when the entire IntelliJ project is closed, not when the LSP server stops or crashes.Disposer.register(file.getProject(), this);
2. LanguageServerWrapper Does Not Track or Cancel Feature Futures
- When the LSP server terminates/crashes unexpectedly, the
unexpectedServerStopHandlertriggers thestop()sequence inLanguageServerWrapper(LanguageServerWrapper.java:L1603). stop()disposes thelanguageClient, disposes theDocumentContentSynchronizerfor all opened documents, and cancels the launcher listening thread.- However,
LanguageServerWrapperdoes not maintain references to the individual request futures (e.g., completion, document symbols) created by the variousAbstractLSPFeatureSupportcomponents. Consequently, it does not cancel or fail them.
3. LSP4J Abrupt Stream Closure Pitfalls
- Under normal circumstances, LSP4J's
RemoteEndpointtracks outstanding request futures. - However, if the LSP server process crashes or is killed abruptly, the stream throws a sudden
IOException(such as aBroken Pipe). In these scenarios, LSP4J does not automatically cancel or complete outstanding request futures in all code paths unless the graceful shutdown/cleanup protocol completes. - Any future that does not get completed exceptionally by LSP4J will remain in an unresolved state permanently.
4. Server Status Changes are Not Propagated to Active Feature Supports
- Although
LanguageServerWrapper.updateStatus()triggers status updates likeServerStatus.stoppingorServerStatus.stopped, thehandleServerStatusChanged()hooks inLanguageClientImplandLSPClientFeaturesare empty placeholders:public void handleServerStatusChanged(@NotNull ServerStatus serverStatus) { // Do nothing } - There is no listener or event propagation mechanism to inform active
AbstractLSPFeatureSupportinstances that the server has terminated, so they never callcancel()to clear and reject their pendingCancellationSupportandCompletableFuturestates.
Summary of Impact
Because the wrapper has no tracking of these feature-specific futures and the LSPFileSupport remains alive on the PsiFile without receiving status updates, any pending futures that LSP4J fails to resolve will hang indefinitely. Any part of the IDE awaiting these futures (using .get(), .join(), or awaitWithCheckCanceled()) will continue to block or leak memory.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with LSPFileSupport.java and LanguageServerWrapper.java, focusing on the unexpectedServerStopHandler, stop(), updateStatus(), and the server-status hooks in LanguageClientImpl and LSPClientFeatures. Trace how AbstractLSPFeatureSupport instances retain pending futures and define completion or cancellation behavior for requests after an unexpected server stop. Done means pending requests no longer hang indefinitely when the LSP server crashes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100