diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-03 13:11:14 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-03 13:11:14 -0300 |
| commit | e81b63106b83bce66641e8dd27d6aa348252baf1 (patch) | |
| tree | 2bdd2427353f5fff7fa1c976194467a5da3a7c96 /src/CHANGELOG.md | |
| parent | ffc8c1f6f19a5dc48e98f99938b438baf9a97165 (diff) | |
| download | pardes-e81b63106b83bce66641e8dd27d6aa348252baf1.tar.gz pardes-e81b63106b83bce66641e8dd27d6aa348252baf1.zip | |
detached: a big screen can attach, and the frame it asks for fits the wire
Two defects, and either fix alone makes the other one worse.
No frontend ever clamped its window to the protocol's grid ceiling — the hello
carried it raw — so a 4K display at a small font, already past max_rows 128,
had its geometry refused by the session's decoder as BadValue. That path
answers with close(.protocol) and no refuse behind it, so the frontend was told
only that the session "hung up on the connect": at a session with all 32 slots
free. client.zig now asks for the largest grid the wire carries, which is what
its own GEOMETRY note already promises a frontend gets — the session is drawn
at its own size in the corner of a bigger window, exactly as when another
frontend is the smaller one. A ZERO geometry is dropped rather than clamped,
because the session grid is the smallest common one and a frontend reporting 1
would collapse everybody else; TIOCGWINSZ answers 0x0 during a teardown and the
tty shell forwarded it, which was the same mute hangup by another route.
That clamp alone would have replaced one bug with a worse one. max_cols *
max_rows is 65536 and a run's length prefix is a u16, so the single grid legal
at both bounds is the one grid whose full frame — and an attach always produces
a full frame — cannot be described by one run. encodeFrame's @intCast panicked
in a safe build and was illegal behaviour in a fast one. The encoder splits the
run instead, bounding the CURSOR rather than the run because the gap lookahead
runs ahead of it, and frameBound had already paid for the extra header.
wire.version 1 -> 2 for the same reason: the geometry a v2 frontend now asks
for is one a v1 daemon panics encoding, and `zig build` replacing the binary
under a running session is exactly what that field exists for. A v1 daemon
answers Refusal.version instead of dying with every pane shell it owns.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016Q4RATpafkwahrovHQLKRf
Diffstat (limited to 'src/CHANGELOG.md')
| -rw-r--r-- | src/CHANGELOG.md | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/CHANGELOG.md b/src/CHANGELOG.md index 4fef47fc..66c9fb0c 100644 --- a/src/CHANGELOG.md +++ b/src/CHANGELOG.md @@ -26,6 +26,30 @@ own in the process: the macOS build roots at `macos.zig`, so the one in `main.zig` had never run there — in the shell with the least useful stderr of the four. +- A big screen can attach to a detached session. The wire's grid ceiling is + 512x128 and no frontend ever clamped to it — the hello carried the window + raw — so a 4K display at a small font, which is already past 128 rows, had + its geometry refused by the session's decoder as `BadValue`. That path + answers with `close(.protocol)` and no `refuse` behind it, so the frontend + reported the one thing a bare hangup can mean: "that session hung up on the + connect", at a session with all 32 slots free. `client.zig` now asks for the + largest grid the protocol carries, which is what its own GEOMETRY note + already promises a frontend gets — the session is drawn at its own size in + the corner of a bigger window, exactly as when another frontend is the + smaller one. A zero geometry is dropped rather than clamped, because the + session grid is the smallest common one and a frontend reporting 1 would + collapse everybody else: `TIOCGWINSZ` answers 0x0 during a teardown and the + tty shell forwarded it, so that was the same mute hangup by another route. + The clamp alone would have replaced one bug with a worse one: `max_cols * + max_rows` is 65536 and a run's length prefix is a `u16`, so the single grid + legal at both bounds is the one grid whose full frame — and an attach always + produces a full frame — cannot be described by one run. It panicked on the + `@intCast` in a safe build and was illegal behaviour in a fast one. The + encoder splits the run instead, which `frameBound` had already paid for, and + the protocol version is bumped to 2: the geometry a v2 frontend now asks for + is one a v1 daemon panics encoding, so a mixed pair — `zig build` replacing + the binary under a running session — meets a `Refusal.version` instead of + losing every pane shell the daemon owns. - A filtered terminal costs what an unfiltered one does. `Filter`'s second stage asked `RGB.contrast` for every cell it painted, and that call ends in `std.math.pow` six times over — a libm round trip per cell, per frame, to |
