diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-27 20:51:09 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:14 -0300 |
| commit | a458b6e610ed573b987ade7c0048663e57fb7191 (patch) | |
| tree | 8afecb4478b3d9d76df55aa67d6183785fcdc5e6 /src/ninep/tree.zig | |
| parent | c3e2cd3b854964ca7db3798cb8750ee6d0833057 (diff) | |
| download | pardes-a458b6e610ed573b987ade7c0048663e57fb7191.tar.gz pardes-a458b6e610ed573b987ade7c0048663e57fb7191.zip | |
Answer a held read by its cloud9 ticket, refuse a second, and say a pane shut down
The held read is now kept by the Ticket cloud9's Conn.hold() gives its
park and answered through Conn.answerWith(), which makes the answer only
while that very park still waits, instead of walking the engine's slots
by tag; pardes no longer reaches into the engine for it. A second read on
an open whose read is held fails with file in use rather than sitting
parked where nothing answers it, and a read that waits with no open
record to hold it is logged and asserted on. A read on an event or
pty/data open whose pane closed answers acme's "window shut down"
(editors/acme/xfid.c:1005). The pane keeps its run's and its lock's open
handles, checked through openOf on use, not record indices. Docs: lock
from a shell needs a held fd, and a command that clears the screen may
read as cut.
Needs cloud9 zvuqvnzy (cca47d63), which adds Conn.hold, waiting and
answerWith; build.zig.zon still pins 82d8152c until that is pushed and
re-pinned.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep/tree.zig')
| -rw-r--r-- | src/ninep/tree.zig | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/src/ninep/tree.zig b/src/ninep/tree.zig index c9e7b31a..f93ab203 100644 --- a/src/ninep/tree.zig +++ b/src/ninep/tree.zig @@ -64,6 +64,7 @@ pub const e_bad_event = "bad event syntax"; /// A second open reading a file whose reads consume: rio's word for it /// (windows/rio/xfid.c:25), which 9ns turns into EBUSY. pub const e_in_use = "file in use"; +pub const e_shut_down = "window shut down"; fn reads(omode: u8) bool { return omode & 3 != 1; // OWRITE is the one access mode that never reads @@ -136,7 +137,7 @@ pub const Open = struct { /// `asker` is the connection the read came on, which only the listener /// knows. - pub const Held = struct { asker: *anyopaque, req: Req }; + pub const Held = struct { asker: *anyopaque, req: Req, ticket: cloud9.fs.Ticket }; pub fn deinit(o: *Open, gpa: std.mem.Allocator) void { switch (o.what) { @@ -655,13 +656,13 @@ fn releaseHandle(p: *Pardes, req: Req) void { pn.fs.pty_out.clearAndFree(p.gpa); }, // The command runs on in the shell; nobody is waiting for it any more. - .run => if (pn.fs.run == @as(u8, @intCast(req.handle - 1))) { + .run => if (pn.fs.run == req.handle) { pn.fs.run = null; }, // Closing the open that holds the lock gives it up, as acme's clunk // of its ctlfid does (editors/acme/xfid.c:211); a write parked on // `lock` goes again. - .ctl => if (pn.fs.lock == @as(u8, @intCast(req.handle - 1))) { + .ctl => if (pn.fs.lock == req.handle) { pn.fs.lock = null; pardes.turn.parked = true; }, @@ -717,7 +718,13 @@ fn read(p: *Pardes, req: Req, target: Target) Reply { .pane => |t| { // A run's answer outlives the pane it ran in. if (t.file == .pty_run and req.handle != 0) return pty.readRun(p, req); - const id = p.paneBySerial(t.serial) orelse return Reply.fail(req.tag, E.NOENT); + const id = p.paneBySerial(t.serial) orelse { + // An event or pty/data read the pane closed under: acme's + // answer to the same (editors/acme/xfid.c:1005). + if (openOf(p, req)) |o| if (o.what == .event or o.what == .pty_data) + return failText(req.tag, E.IO, e_shut_down); + return Reply.fail(req.tag, E.NOENT); + }; const pn = p.panes[id].?; if (t.file.inPty() and !pn.isTerminal()) return Reply.fail(req.tag, E.NOENT); return pane.read(p, req, id, pn, t.file); |
