Skip to content

Tests test_no_server_* and test_raise_if_dead_no_server_raises fail when stale tmux daemon exists at hardcoded socket name #664

Description

@tony

Summary

Three tests in tests/test_server.py fail when a tmux server happens to be alive at the exact socket path they hardcode. Because the tests register no cleanup, any daemon that ends up at one of those socket names — from a prior crashed run, manual debugging, or anything else — sticks around and breaks them on every subsequent run, even in isolation.

The library code (Server.is_alive, Server.cmd, Server.raise_if_dead, tmux_cmd) is correct. This is purely a test-isolation defect.

Affected tests (tests/test_server.py)

def test_no_server_sessions() -> None:
    server = Server(socket_name="test_attached_session_no_server")
    assert server.sessions == []

def test_no_server_attached_sessions() -> None:
    server = Server(socket_name="test_no_server_attached_sessions")
    assert server.attached_sessions == []

def test_no_server_is_alive() -> None:
    dead_server = Server(socket_name="test_no_server_is_alive")
    assert not dead_server.is_alive()

def test_raise_if_dead_no_server_raises() -> None:
    dead_server = Server(socket_name="test_attached_session_no_server")
    with pytest.raises(subprocess.CalledProcessError):
        dead_server.raise_if_dead()

(Note: test_no_server_sessions and test_raise_if_dead_no_server_raises share the same hardcoded socket name test_attached_session_no_server — a copy-paste leftover that matches neither function name.)

Reproduction

$ tmux -L test_no_server_is_alive new-session -d
$ uv run pytest tests/test_server.py::test_no_server_is_alive -v

Result:

tests/test_server.py:210: in test_no_server_is_alive
    assert not dead_server.is_alive()
E   assert not True

Same pattern reproduces for the other two:

$ tmux -L test_attached_session_no_server new-session -d
$ uv run pytest tests/test_server.py::test_no_server_sessions tests/test_server.py::test_raise_if_dead_no_server_raises

Root cause

  • The tests construct Server with hardcoded socket_name strings.
  • They register no finalizer, so anything that creates a daemon at /tmp/tmux-<uid>/<socket_name> persists indefinitely.
  • tmux does not always unlink(2) its socket on non-graceful exit, so leftover socket files accumulate in /tmp/tmux-<uid>/.
  • A later test run's Server(socket_name=...).is_alive() correctly reports True because the daemon really is alive — the test's assumption that the name is unused is the wrong premise.

In my environment two such daemons had been listening since 3 days prior, with PIDs 984553 and 984791, on /tmp/tmux-1000/test_attached_session_no_server and /tmp/tmux-1000/test_no_server_is_alive respectively. lsof -U | grep tmux confirmed live LISTEN sockets on both paths.

Proposed fix

Use the existing server fixture (src/libtmux/pytest_plugin.py:144-182) — it already produces a Server with a unique random socket name (libtmux_test{N}) and registers a _reap_test_server finalizer that kills any daemon and unlinks the socket file. A freshly-created Server with a unique name has no daemon running on it, so it is the "dead server" these tests need.

def test_no_server_sessions(server: Server) -> None:
    assert server.sessions == []

def test_no_server_attached_sessions(server: Server) -> None:
    assert server.attached_sessions == []

def test_no_server_is_alive(server: Server) -> None:
    assert not server.is_alive()

def test_raise_if_dead_no_server_raises(server: Server) -> None:
    with pytest.raises(subprocess.CalledProcessError):
        server.raise_if_dead()

This eliminates every hardcoded socket name, removes the typo coupling, and inherits cleanup automatically.

Workaround for affected users

$ tmux -L test_attached_session_no_server kill-server 2>/dev/null
$ tmux -L test_no_server_is_alive kill-server 2>/dev/null
$ tmux -L test_no_server_attached_sessions kill-server 2>/dev/null
$ rm -f /tmp/tmux-$(id -u)/{test_attached_session_no_server,test_no_server_is_alive,test_no_server_attached_sessions}

Environment

  • libtmux: master @ 4e19628 ("py(deps[dev]) Bump dev packages")
  • Python 3.10+
  • tmux: system tmux on Linux 6.6.87.2-microsoft-standard-WSL2

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions