summaryrefslogtreecommitdiff
path: root/src/ninep/tree.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 02:21:57 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commit90f5c414a90afec978c8c0add58fd2a7e29acbaa (patch)
tree21a73a5ec603705cf789d39da73cceea425d9420 /src/ninep/tree.zig
parenteece0fbe709142f6731b7dd2e84009c3a18a3806 (diff)
downloadpardes-90f5c414a90afec978c8c0add58fd2a7e29acbaa.tar.gz
pardes-90f5c414a90afec978c8c0add58fd2a7e29acbaa.zip
A read on a closed pane's event ends ENOENT, and the pane cap is ENOSPC
9ns reads an error's words, not its errno: "window shut down" came out as EIO where every other file of a gone pane gives ENOENT, and "no pane slots" as EIO. The event and pty/data reads a pane closed under now say "no such pane: its window shut" (ENOENT), and the cap says "no space for a pane: 64 max" (ENOSPC; 9ns has no word for ENFILE). Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep/tree.zig')
-rw-r--r--src/ninep/tree.zig13
1 files changed, 8 insertions, 5 deletions
diff --git a/src/ninep/tree.zig b/src/ninep/tree.zig
index 278732b5..aec3cab7 100644
--- a/src/ninep/tree.zig
+++ b/src/ninep/tree.zig
@@ -66,7 +66,10 @@ 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";
+/// A read held on a pane's event or pty/data that the pane closed under.
+/// acme says "window shut down" (xfid.c:1005), which 9ns reads as EIO;
+/// these words read as ENOENT, what every other file of a gone pane gives.
+pub const e_shut_down = "no such pane: its window shut";
/// Tremove closes a pane; nothing else in the tree is created or destroyed by
/// the protocol, and wstat stays a truncation. Making a pane is an open of
@@ -709,7 +712,7 @@ fn open(p: *Pardes, req: Req, target: Target) Reply {
// pane it made, so reading it twice answers the same one and
// closing it leaves the pane alone.
.new => {
- const slot = p.freeSlot() orelse return failText(req.tag, E.NFILE, std.fmt.bufPrint(&p.fs.ename, "pane/new: " ++ pardes.Messages.no_pane_slots, .{pardes.MAX_PANES}) catch "no pane slots");
+ const slot = p.freeSlot() orelse return failText(req.tag, E.NOSPC, std.fmt.bufPrint(&p.fs.ename, "pane/new: " ++ pardes.Messages.no_pane_slots, .{pardes.MAX_PANES}) catch "no space for a pane");
p.newScratchFor(p.active, .fs);
const made = p.panes[slot] orelse return Reply.fail(req.tag, E.NFILE);
return .{ .tag = req.tag, .handle = made.serial };
@@ -939,7 +942,7 @@ fn readFile(p: *Pardes, req: Req, target: Target) Reply {
// 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 failText(req.tag, E.NOENT, e_shut_down);
return Reply.fail(req.tag, E.NOENT);
};
const pn = p.panes[id].?;
@@ -1427,9 +1430,9 @@ test "at the pane cap, pane/new, look and New each say so, and look reads back e
const new = @intFromEnum(TopFile.new);
while (p.freeSlot() != null) try testing.expectEqual(Status.ok, call(p, .{ .tag = 1, .op = .open, .node = new }).reply.status);
var want: [64]u8 = undefined;
- const said = try std.fmt.bufPrint(&want, "no pane slots: {d} max", .{pardes.MAX_PANES});
+ const said = try std.fmt.bufPrint(&want, "no space for a pane: {d} max", .{pardes.MAX_PANES});
const refused = call(p, .{ .tag = 2, .op = .open, .node = new });
- try testing.expectEqual(E.NFILE, refused.errno());
+ try testing.expectEqual(E.NOSPC, refused.errno());
try testing.expect(std.mem.endsWith(u8, refused.reply.ename, said));
try testing.expect(th.logHas(p, said));
// A look that would open a pane fails its write, and says the same.