Commit ff59792
fix: sesh channel fixes and inherit TTY fds for interactive actions (#1052)
Closes joshmedeski/sesh#368
- Fix an interaction between \`tv\`'s execute actions and \`tmux
attach-session\` on macOS that surfaces as \`open terminal failed: can't
use /dev/tty\` when an action shells out to tmux from outside a running
tmux client.
- Let \`sesh\` (and other session managers) manage their own ordering by
adding \`frecency = false\` / \`no_sort = true\` to the built-in
\`sesh\` channel, and tidy a couple of formatting nits in
\`cable/unix/sesh.toml\`.
## The TTY bug
\`attach_to_tty\` in \`television/utils/command.rs\` unconditionally
reopens \`/dev/tty\` and dup's the resulting FD onto the child's
stdin/stdout/stderr before every execute/fork action. That behaviour is
necessary when \`tv\` is invoked with piped streams (\`ls | tv --preview
...\`), but in the normal interactive case it hands the child a file
descriptor whose kernel path is \`/dev/tty\`.
On macOS, \`ttyname()\` on such an FD resolves back to \`/dev/tty\`
rather than to the underlying pty device (e.g. \`/dev/ttys001\`). When
the child eventually runs \`tmux attach-session\`, tmux's client code
rejects that path in \`tty.c\` — it explicitly refuses \`/dev/tty\`
because it needs an unambiguous, openable device — and exits 1. The user
sees:
\`\`\`
open terminal failed: can't use /dev/tty
ERROR
Failed to attach to tmux session: exit status 1.
\`\`\`
Running the exact same \`sesh connect <session>\` command from the same
shell (fish/zsh/bash) outside of \`tv\` works fine, because the shell's
stdin is the real pty slave, not a dup of \`/dev/tty\`. That's the tell
that the issue lives in \`attach_to_tty\`, not in sesh/tmux.
This only surfaces now because previously the path most people hit was
\`tv sesh\` from inside tmux, which takes the \`tmux switch-client\`
branch in sesh — \`switch-client\` is a non-interactive tmux subcommand
and tolerates any FD that \`isatty()\` accepts, so the bug stays hidden.
### The fix
Check whether the inherited stdin/stdout/stderr are already TTYs (via
\`std::io::IsTerminal\`, no new dependencies). If so, inherit them as-is
so the child sees the real pty device path. Otherwise fall through to
the existing \`/dev/tty\` fallback so piped invocations keep working.
Before calling \`execute_action\`, \`tv\` already tears down its TUI
(\`RenderingTask::Quit\`, \`disable_raw_mode\`, etc. in \`app.rs\`), so
the inherited FDs are in cooked mode — safe to pass through.
## Channel config tweak
The \`sesh\` channel now sets:
\`\`\`toml
frecency = false # handled by sesh
no_sort = true # handled by sesh
\`\`\`
\`sesh list\` already returns sessions in the order users expect
(recently-used tmux sessions first, then config/zoxide entries).
Layering \`tv\`'s frecency and default sort on top of that reorders the
list in confusing ways — better to defer to sesh.
Also reflowed the \`command = [...]\` array and the \`ctrl-d\` binding
to match the formatter's output.
## Test plan
- [x] \`cargo check --lib\` clean
- [x] \`cargo build\` clean (debug binary exercised manually)
- [x] \`tv sesh\` from outside tmux (server running, no attached client)
attaches to an existing session and returns cleanly on detach
- [x] \`tv sesh\` from inside tmux still switches (unchanged path)
- [ ] \`ls | tv\` style piped invocation — \`/dev/tty\` fallback still
engaged; preview/actions still usable
- [ ] Linux sanity check (macOS-specific symptom, but the fix is
portable)
The test suite wasn't run because \`libghostty-vt-sys\` in this checkout
requires zig 0.15.2 while my local zig is 0.16.0 — unrelated to this
change.
---------
Co-authored-by: Alex Pasmantier <47638216+alexpasmantier@users.noreply.github.com>1 parent ec0db0a commit ff59792
2 files changed
Lines changed: 22 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
20 | 22 | | |
21 | 23 | | |
22 | 24 | | |
23 | 25 | | |
24 | 26 | | |
25 | 27 | | |
26 | 28 | | |
27 | | - | |
| 29 | + | |
28 | 30 | | |
29 | 31 | | |
30 | 32 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
204 | 204 | | |
205 | 205 | | |
206 | 206 | | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
207 | 221 | | |
208 | 222 | | |
209 | 223 | | |
| |||
0 commit comments