summaryrefslogtreecommitdiff
path: root/src/ninep/pty.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-27 20:51:09 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commita458b6e610ed573b987ade7c0048663e57fb7191 (patch)
tree8afecb4478b3d9d76df55aa67d6183785fcdc5e6 /src/ninep/pty.zig
parentc3e2cd3b854964ca7db3798cb8750ee6d0833057 (diff)
downloadpardes-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/pty.zig')
-rw-r--r--src/ninep/pty.zig21
1 files changed, 16 insertions, 5 deletions
diff --git a/src/ninep/pty.zig b/src/ninep/pty.zig
index 936f9b73..49f52c82 100644
--- a/src/ninep/pty.zig
+++ b/src/ninep/pty.zig
@@ -164,7 +164,7 @@ pub fn writeRun(p: *Pardes, req: Req, id: usize, pane: *Pane) Reply {
const marks = &state.stream.handler;
if (pf.unmarked) {
answer(p, slot, "error no prompt marks", .{});
- } else if (pf.run != null or marks.phase != .input or
+ } else if (waitingRun(p, pane) != null or marks.phase != .input or
!pardes.panes.Terminal.promptInputEmpty(pane) or p.hostTtyTaken(id))
{
// Something is running, someone has typed at the prompt, or the
@@ -180,7 +180,7 @@ pub fn writeRun(p: *Pardes, req: Req, id: usize, pane: *Pane) Reply {
p.emitWrite(id, line);
p.emitWrite(id, "\r");
slot.phase = .sent;
- pf.run = @intCast(req.handle - 1);
+ pf.run = req.handle;
}
return .{ .tag = req.tag, .written = @intCast(req.data.len) };
}
@@ -217,7 +217,7 @@ pub fn noteMarks(p: *Pardes, id: usize, pane: *Pane) void {
if (comptime !pardes.panes.Terminal.enabled) return;
const state = pane.terminal orelse return;
const pf = &pane.fs;
- const slot = &p.fs.opens[pf.run orelse return].what.run;
+ const slot = waitingRun(p, pane) orelse return;
const marks = &state.stream.handler;
if (marks.phase != .input) return;
// ponytail: a prompt redrawn before the command starts (a resize in that
@@ -297,11 +297,22 @@ pub fn noteMarks(p: *Pardes, id: usize, pane: *Pane) void {
/// The pane closed or its shell was replaced: the command's end will never
/// be reported, so the run says so instead of waiting forever.
pub fn shellGone(p: *Pardes, pane: *Pane) void {
- const idx = pane.fs.run orelse return;
- answer(p, &p.fs.opens[idx].what.run, "error shell gone", .{});
+ answer(p, waitingRun(p, pane) orelse return, "error shell gone", .{});
pane.fs.run = null;
}
+/// The run waiting on this shell's command. The pane keeps its open's
+/// handle, which names that open only on the node it was opened on, so it
+/// is looked up the way a request's is; one that no longer names a run is
+/// forgotten.
+fn waitingRun(p: *Pardes, pane: *Pane) ?*Run {
+ const handle = pane.fs.run orelse return null;
+ if (tree.openOf(p, .{ .tag = 0, .op = .read, .node = tree.Node.of(pane.serial, .pty_run), .handle = handle })) |o|
+ if (o.what == .run) return &o.what.run;
+ pane.fs.run = null;
+ return null;
+}
+
const e_bad_line = "bad command line";
pub fn readData(p: *Pardes, req: Req, pf: *pane_files.State) Reply {