Fix: Exceptions raised during LanguageServerManager.start did not stop the language server subprocess if it was already started

start() now catches an exception from _start_server(), stops the process if it is
already running, and re-raises. 

Fixes #1949
This commit is contained in:
Amir Fathi authored and GitHub committed 2026-09-02 12:53:41 +02:00
1 parent 43ae0211d7
commit dc59a8931c
5 files changed
+174 -1

No files matched your search

+3
View File
@@ -144,6 +144,9 @@ class LanguageServerManager:
language_servers[thread.ls_id] = thread.language_server
# If any server failed to start up, raise an exception and stop all started language servers.
# A server whose own thread raised has already stopped its own process, since
# SolidLanguageServer.start() cleans up after itself on failure; only the servers that
# started successfully (and are therefore absent from `exceptions`) still need stopping.
# We intentionally fail fast here. The user's intention is to work with all the specified languages,
# so if any of them is not available, it is better to make symbolic tool calls fail, bringing the issue to the
# user's attention instead of silently continuing with a subset of the language servers and potentially
+11 -1
View File
@@ -3179,7 +3179,17 @@ class SolidLanguageServer(ABC):
"""
log.info(f"Starting language server {self.language_server.ls_id} for {self.language_server.repository_root_path}")
self.server_started = True
self._start_server()
try:
self._start_server()
except Exception:
# `_start_server()` may raise after already spawning the underlying process (a
# capability assertion or an initialize() timeout firing post-spawn). Stop it here
# so a failed start never leaves an orphaned process behind, regardless of caller.
if self.is_running():
self.stop()
else:
self.server_started = False
raise
return self
def stop(self, shutdown_timeout: float = 2.0) -> None: