Fix HLSL language server leaving orphaned processes on shutdown

The base _shutdown() calls process.terminate() directly on the subprocess,
which on Windows with shell=True only kills the cmd.exe wrapper, leaving
the shader-language-server binary running as an orphan. Override stop() in
HlslLanguageServer to use psutil to terminate the full process tree before
the standard shutdown.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
TheSmallKiwiandClaude Opus 4.6 committed 2026-03-13 20:07:22 -04:00
1 parent 6d6f55308f
commit 97130e7c13
1 file changed
+33
@@ -9,6 +9,7 @@ import pathlib
import shutil
from typing import Any, cast
import psutil
from overrides import override
from solidlsp.ls import LanguageServerDependencyProvider, LanguageServerDependencyProviderSinglePath, SolidLanguageServer
@@ -213,6 +214,38 @@ class HlslLanguageServer(SolidLanguageServer):
self.server.notify.initialized({})
@override
def stop(self, shutdown_timeout: float = 2.0) -> None:
"""Kill the shader-language-server process tree before the standard shutdown.
The base _shutdown() calls process.terminate() directly on the subprocess,
which on Windows with shell=True only kills the cmd.exe wrapper, leaving
the actual shader-language-server binary running as an orphan. We use psutil
to terminate the full process tree first.
"""
process = self.server.process if self.server else None
if process and process.pid and process.returncode is None:
try:
parent = psutil.Process(process.pid)
children = parent.children(recursive=True)
for child in children:
try:
child.terminate()
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
psutil.wait_procs(children, timeout=2)
for child in children:
try:
if child.is_running():
child.kill()
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
except Exception as e:
log.debug(f"Error cleaning up shader-language-server process tree: {e}")
super().stop(shutdown_timeout)
@override
def is_ignored_dirname(self, dirname: str) -> bool:
"""Ignore Unity-specific directories that contain no user-authored shaders."""