Skip to content

fix: do not end a new session at once when its initiating view closed - #3048

Merged
rchl merged 6 commits into
mainfrom
test/stable-setup-session
Oct 3, 2026
Merged

rchl merged 6 commits into
mainfrom
test/stable-setup-session

Conversation

@rchl

@rchl rchl commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Fixes the flaky TextDocumentTestCase.setUpClass timeouts on macOS CI (for example https://github.com/sublimelsp/LSP/actions/runs/36761225504 and https://github.com/sublimelsp/LSP/actions/runs/36917769576).

Cause

A trace from a failing macOS run showed this sequence:

  1. The view of the previous test is still closing when the next test calls add_config.
  2. The queued restart_sessions_async registers all known listeners again, including the listener of the closing view. That view is still valid, so a session starts for it. The new test view waits in the queue.
  3. When the session is ready, the old view is closed. _dequeue_listener_async adds the session to _sessions, finds that it has no views and ends it at once. The test can find the session in that short time.
  4. Then LSP starts a second server for the new test view. The test keeps the stopping session and times out. The second session is never ended, so the next test finds a leftover file watcher (1 != 0).

This is also a real issue outside the tests: when the view that started a session closes during initialize, LSP starts a second server for nothing.

Fix

When a new session has no views, do not end it at once. End it only if no view uses it after a short delay (Session.end_async_if_unused). This is the same idle shutdown that unregister_session_view_async already uses. The pending listener then uses the same session.

Testing

  • macOS CI, 10 parallel runs before the fix: 2 failed.
  • macOS CI, 10 parallel runs with the fix: all passed. The trace showed the race 7 times in 4 runs, and each time the new view used the same session.
  • Full suite in Docker (Linux): passed.

The branch has temporary commits (macOS-only matrix, 10 attempts, trace prints) and a final cleanup commit that removes them. The net change is in plugin/core/sessions.py and plugin/core/windows.py only. Squash on merge.

πŸ€– Generated with Claude Code

rchl and others added 6 commits October 1, 2026 22:58
On macOS CI, setUpClass sometimes times out while it waits for the session
to become ready. The test captured the first session that it found, but
that session can stop before it is seen as ready, and then LSP starts a new
session. Wait for a ready session and capture that session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The view that started a session can close while the server initializes. Then _dequeue_listener_async ended the new session at once, although a pending listener could still use it, and started a second server. For a short time, the stopping session was visible in WindowManager._sessions. This made TextDocumentTestCase.setUpClass flaky on macOS CI.

End the session only if no view uses it after a short delay. This is the same idle shutdown that unregister_session_view_async uses.

This commit also reverts the test change from the previous commit, because the test change only hid the problem.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rchl rchl changed the title test: capture the test session only when it is ready fix: do not end a new session at once when its initiating view closed Oct 1, 2026
@rchl
rchl marked this pull request as ready for review October 1, 2026 21:27
@rchl
rchl merged commit f61e26e into main Oct 3, 2026
9 checks passed
@rchl
rchl deleted the test/stable-setup-session branch October 3, 2026 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant