`Server.__exit__` kills any live server, including one it did not start
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
Research direction
Start in src/libtmux/server.py at init and exit around lines 267-285, then read docs/topics/context_managers.md and compare the sibling context managers. Add a regression test showing that a pre-existing server survives a with block, document the shared-server hazard, and verify the chosen lifecycle behavior preserves the intended default.
Written by the indexing model from the issue text.
Description
Filed against tmux-python/libtmux v0.62.0. Found while writing tested documentation examples that isolate tmux under a temporary TMUX_TMPDIR.
What happens
with Server(...) as server: kills the server on exit whenever it is alive, unconditionally. There is no kill_on_exit=False, no "only kill what I started", and no way to use the context manager purely for scoping.
src/libtmux/server.py#L267-L285—__exit__
if self.is_alive():
self.kill()
A Server is a handle, not a connection, and the same handle addresses a server whether or not this process started it. So the context manager cannot tell "the server I just booted" from "the server the user has been working in all day", and it destroys both.
The sharpest form: with Server() as server: — no arguments, so the default socket — kills the reader's running tmux and every session in it. That is a plausible thing to write after reading the class docstring, and the failure is silent and total.
Recreation
import os, tempfile
os.environ["TMUX_TMPDIR"] = tempfile.mkdtemp(prefix="repro-")
from libtmux.server import Server
Server(socket_name="preexisting").new_session(session_name="important-work")
print("before:", [s.session_name for s in Server(socket_name="preexisting").sessions])
with Server(socket_name="preexisting") as server:
print("inside:", server.is_alive())
print("after :", Server(socket_name="preexisting").is_alive(), "<- the session is gone")
Observed on libtmux v0.62.0 / tmux 3.7b:
before: ['important-work']
inside: True
after : False <- the session is gone
The with block did nothing except enter and exit, and a session it never created is gone. Drop the TMUX_TMPDIR line and the same script destroys the real default server.
Note on the sibling context managers
Session, Window and Pane have the same shape — __exit__ kills the object if it still exists — but the blast radius there is bounded by what the object is, and killing a session you were handed is at least proportionate. A server is different in kind: it is shared, process-wide, and typically not yours.
Documented in docs/topics/context_managers.md, which describes the kill-on-exit behaviour but not the shared-server hazard.
What a fix needs
- Add
kill_on_exit: bool = TruetoServer.__init__, honoured by__exit__. Keeps the current default, gives callers an out. Cheapest change, no behaviour break. - Better, if a break is acceptable in a pre-1.0 minor: only kill a server this handle started.
Serveralready knows whether it booted the daemon —new_sessionis the call that starts one — so record that and have__exit__respect it. This makes the destructive path opt-in by construction rather than by remembering a keyword. - Either way: document the hazard on
Server.__enter__/__exit__and indocs/topics/context_managers.md, in the same terms as the recreation above, and add a regression test that a pre-existing server survives awithblock.
Option 2 with a kill_on_exit=True escape hatch would cover both audiences. If neither is wanted, the minimum is a loud warning in the docstring — the current one says "killing the server if it exists" without saying whose.
- Dominant language
- Python
- Stars
- 1.2k
- Forks
- 127
- Avg merge
- 2h 13m
- Merged PRs (30d)
- 1
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from tmux-python/libtmux
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
tmux-python/libtmux#759 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
tmux-python/libtmux#745 · 2 comments ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
tmux-python/libtmux#744 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
tmux-python/libtmux#731 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
tmux-python/libtmux#654 ·
All issues in tmux-python/libtmux
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
use-agent-os/agent-os#3314 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
BasedHardware/omi#15662 · 1 comment ·
-
documentation help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
AiursoftWeb/AnduinOS-2#19 ·