fix(pytest_plugin): unlink socket file on fixture teardown#661
Merged
Conversation
The `server` and `TestServer` fixtures called `server.kill()` on teardown but never unlinked the socket file under `/tmp/tmux-<uid>/`. tmux does not reliably `unlink(2)` its own socket on non-graceful exit — so every test run that used these fixtures left behind stale socket entries that accumulated indefinitely (10k+ observed on long-lived dev machines). Introduce `_reap_test_server(socket_name)` helper that kills the daemon (if alive) *and* unconditionally unlinks the computed socket path. `Server(socket_name=...)` does not populate `socket_path`, so the helper recomputes `$TMUX_TMPDIR/tmux-<uid>/<name>` the same way tmux does. Both fixture finalizers delegate to it. Cleanup errors are suppressed via `contextlib.suppress` so a finalizer failure never masks the real test failure, and races with pytest-xdist workers (concurrent access to the same directory) stay benign. Kills ride through `LibTmuxException`/`OSError`; unlinks use `missing_ok=True` and swallow `OSError`. Added regression tests: - `_reap_test_server` unlinks a real socket file after killing a live daemon. - Reaping a never-created socket is a silent no-op. - Reaping `None` is tolerated for symmetry with `Server.socket_name`'s nullable type. Fixes #660
5 tasks
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #661 +/- ##
==========================================
+ Coverage 46.55% 46.58% +0.03%
==========================================
Files 22 22
Lines 2363 2372 +9
Branches 389 390 +1
==========================================
+ Hits 1100 1105 +5
- Misses 1094 1098 +4
Partials 169 169 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
tony
added a commit
to tmux-python/libtmux-mcp
that referenced
this pull request
Apr 19, 2026
libtmux 0.55.1 ships the pytest-plugin socket-reaper fix (tmux-python/libtmux#661) so the `server` / `TestServer` fixtures now kill the tmux daemon AND unlink the socket file under `/tmp/tmux-<uid>/` on teardown. This bumps the runtime floor and refreshes uv.lock so CI and fresh installs pick up the fix. Verified locally: after the bump, `uv run pytest` leaves a single residual socket per run (down from thousands accumulating across runs pre-fix). The remaining straggler originates outside the standard fixture teardown path and is a separate, minor issue — not a regression. Supersedes the local conftest reaper proposed in #23; that PR can now be closed without merge.
5 tasks
tony
added a commit
to tmux-python/libtmux-mcp
that referenced
this pull request
Apr 19, 2026
why: libtmux 0.55.1 ships the pytest-plugin socket-reaper fix (tmux-python/libtmux#661). The `server` and `TestServer` fixtures now kill the tmux daemon *and* unlink the socket file under `/tmp/tmux-<uid>/` on teardown, eliminating the `libtmux_test*` accumulation that downstream consumers like this package inherited. Bumping the floor makes the fix part of the install contract; the lockfile refresh guarantees CI and fresh installs pick it up. what: - **`pyproject.toml`** — dependency specifier `libtmux>=0.55.0,<1.0` -> `libtmux>=0.55.1,<1.0`. - **`uv.lock`** — regenerated; resolved `libtmux==0.55.0` -> `libtmux==0.55.1`. - **`CHANGES`** — unreleased Dependencies section notes the floor bump and points at the upstream fix. Downstream effect: obsoletes #23 (local conftest socket reaper), which was a workaround for the same leak. Close #23 without merge. Release notes: https://libtmux.git-pull.com/history.html (libtmux 0.55.1 section).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
serverandTestServerfixtures inlibtmux.pytest_plugincalledserver.kill()on teardown but never unlinked the socket file under/tmp/tmux-<uid>/. tmux does not reliablyunlink(2)its own socket on non-graceful exit, so every test run that used these fixtures left behind stale socket entries that accumulated indefinitely (10k+ observed on a long-lived dev machine; surfaced bylibtmux-mcp'slist_serverstool as 43 live leaked servers alongside the filesystem cruft).Introduce
_reap_test_server(socket_name)helper that kills the daemon (if alive) and unconditionally unlinks the computed socket path.Server(socket_name=...)does not populatesocket_path, so the helper recomputes$TMUX_TMPDIR/tmux-<uid>/<name>the same way tmux does. Both fixture finalizers delegate to it.Cleanup errors are suppressed via
contextlib.suppressso a finalizer failure can never mask the real test failure, and races withpytest-xdistworkers stay benign. Kills ride throughLibTmuxException/OSError; unlinks usemissing_ok=Trueand swallowOSError.Test plan
uv run ruff check . --fix --show-fixesuv run ruff format .uv run mypyuv run py.test --reruns 0 -vvv(885 passed, 1 skipped)just build-docsEnd-to-end verification on this machine: before the fix
ls /tmp/tmux-$(id -u) | grep -c libtmux_testwas 10693. After the fix, running the full libtmux suite from a clean/tmp/tmux-<uid>/leaves 0 stale sockets.New regression tests in
tests/test_pytest_plugin.pytest_reap_test_server_unlinks_socket_file— boots a real daemon, confirms the socket file exists, calls_reap_test_server, asserts the file is gone.test_reap_test_server_is_noop_when_socket_missing— the finalizer path when a fixture failed before the daemon started.test_reap_test_server_tolerates_none— nullableServer.socket_nameargument doesn't crash the reaper.Downstream
Surfaced by
tmux-python/libtmux-mcp#20. That repo has a local mitigation PR that can be reverted once this lands.Fixes #660