Summary
The Kotlin Language Server (KLS) is built on IntelliJ IDEA's platform. Each KLS instance creates an idea-system* temporary directory under /tmp. These directories are never cleaned up after the language server shuts down, causing unbounded accumulation across test runs.
Observed Impact
On a developer machine with /tmp mounted as tmpfs (RAM-backed — the default on modern Linux systems), repeated test runs accumulated:
329 x idea-system*/ = 30 GiB in RAM
/tmp (tmpfs): 36 GiB used total
Each KLS instance produces ~52 MB in its idea-system* directory. After 329 test sessions the entire tmpfs was nearly exhausted, starving the system of RAM and swap.
Root Cause
IntelliJ's platform runtime defaults to creating its system directory at /tmp/idea-system<random>/ when no explicit idea.system.path JVM property is set. The KotlinLanguageServer currently passes JAVA_TOOL_OPTIONS (heap size) but does not redirect this path:
# src/solidlsp/language_servers/kotlin_language_server.py
def create_launch_command_env(self) -> dict[str, str]:
env["JAVA_TOOL_OPTIONS"] = jvm_options # only -Xmx2G by default
return env
The stop() / _shutdown() implementation in SolidLanguageServer terminates the process but performs no filesystem cleanup.
Suggested Fix
Two complementary changes in KotlinLanguageServer:
-
Redirect idea.system.path to a location we control (e.g. inside ls_resources_dir or a tempfile.mkdtemp() created at startup) by appending -Didea.system.path=<path> to JAVA_TOOL_OPTIONS.
-
Clean up on stop — override stop() in KotlinLanguageServer to delete the directory after the process terminates.
Example sketch:
import tempfile, shutil
class KotlinLanguageServer(SolidLanguageServer):
def __init__(self, ...):
self._idea_system_dir = tempfile.mkdtemp(prefix="serena-idea-system-")
...
def create_launch_command_env(self) -> dict[str, str]:
env = super().create_launch_command_env()
jvm_options = env.get("JAVA_TOOL_OPTIONS", "")
env["JAVA_TOOL_OPTIONS"] = f"{jvm_options} -Didea.system.path={self._idea_system_dir}".strip()
return env
def stop(self, shutdown_timeout: float = 2.0) -> None:
super().stop(shutdown_timeout)
if hasattr(self, "_idea_system_dir"):
shutil.rmtree(self._idea_system_dir, ignore_errors=True)
Alternatively the directory can live under ls_resources_dir/kotlin_language_server/system/ — a persistent but bounded cache — if keeping the IntelliJ index across sessions is desirable (faster restarts). In that case no cleanup is needed, but its size should be documented.
Environment
- Platform: Linux (x86-64),
/tmp is tmpfs
- KLS version: 261.13587.0 (default bundled)
- Serena branch:
fix/kill-gradle-daemons-on-shutdown
Related
Summary
The Kotlin Language Server (KLS) is built on IntelliJ IDEA's platform. Each KLS instance creates an
idea-system*temporary directory under/tmp. These directories are never cleaned up after the language server shuts down, causing unbounded accumulation across test runs.Observed Impact
On a developer machine with
/tmpmounted as tmpfs (RAM-backed — the default on modern Linux systems), repeated test runs accumulated:Each KLS instance produces ~52 MB in its
idea-system*directory. After 329 test sessions the entire tmpfs was nearly exhausted, starving the system of RAM and swap.Root Cause
IntelliJ's platform runtime defaults to creating its system directory at
/tmp/idea-system<random>/when no explicitidea.system.pathJVM property is set. TheKotlinLanguageServercurrently passesJAVA_TOOL_OPTIONS(heap size) but does not redirect this path:The
stop()/_shutdown()implementation inSolidLanguageServerterminates the process but performs no filesystem cleanup.Suggested Fix
Two complementary changes in
KotlinLanguageServer:Redirect
idea.system.pathto a location we control (e.g. insidels_resources_diror atempfile.mkdtemp()created at startup) by appending-Didea.system.path=<path>toJAVA_TOOL_OPTIONS.Clean up on stop — override
stop()inKotlinLanguageServerto delete the directory after the process terminates.Example sketch:
Alternatively the directory can live under
ls_resources_dir/kotlin_language_server/system/— a persistent but bounded cache — if keeping the IntelliJ index across sessions is desirable (faster restarts). In that case no cleanup is needed, but its size should be documented.Environment
/tmpistmpfsfix/kill-gradle-daemons-on-shutdownRelated