fix(lsp): cleanup subprocess on failed initialization in StdioTransport.start() #11020

Merged
HAL9000 merged 6 commits from pr_fix/lsp-transport-subprocess-cleanup into master 2026-06-13 20:37:23 +00:00

6 Commits

Author SHA1 Message Date
controller-ci-rerun 1313570efe chore: re-trigger CI [controller]
CI / lint (pull_request) Successful in 58s
CI / quality (pull_request) Successful in 1m6s
CI / typecheck (pull_request) Successful in 1m25s
CI / build (pull_request) Successful in 47s
CI / security (pull_request) Successful in 2m41s
CI / push-validation (pull_request) Successful in 25s
CI / helm (pull_request) Successful in 48s
CI / unit_tests (pull_request) Successful in 10m46s
CI / docker (pull_request) Successful in 1m39s
CI / integration_tests (pull_request) Successful in 18m16s
CI / coverage (pull_request) Successful in 14m5s
CI / status-check (pull_request) Successful in 3s
2026-06-13 16:10:40 -04:00
controller-ci-rerun 07b1b9ecc1 chore: re-trigger CI [controller] 2026-06-13 16:10:40 -04:00
controller-ci-rerun ccaea056b9 chore: re-trigger CI [controller] 2026-06-13 16:10:40 -04:00
controller-ci-rerun 60cb92938a chore: re-trigger CI [controller] 2026-06-13 16:10:40 -04:00
controller-ci-rerun b6530a9c5d chore: re-trigger CI [controller] 2026-06-13 16:10:40 -04:00
HAL9000 c8232c17f4 fix(lsp): cleanup subprocess on failed initialization in StdioTransport.start()
When subprocess.Popen() fails during LSP server initialization (e.g.
FileNotFoundError for missing command or general OSError), partially-allocated
pipe resources and internal file descriptors could be left in an inconsistent
state. This was caused by _process potentially containing a stale reference if
an exception occurred between pipe allocation and the Popen object being fully
returned.

Fix: Add explicit self._process = None resets in three places:
1) Before subprocess.Popen() — ensures clean initial state even across retries
2) In FileNotFoundError handler — guards against intermediate error states
3) In OSError handler — general safety net for all subprocess failures

This prevents:
- Orphaned child processes never terminated (zombie processes)
- File descriptor leaks from partially-allocated pipes
- Transports stuck in ambiguous 'started but not live' state

Tests added: Two new Behave scenarios verify _process is None after both
FileNotFoundError and OSError during start().

ISSUES CLOSED: #10597
2026-06-13 16:10:40 -04:00