From 0f18cc317190c2aaaf0efec4cd6da656cb1f3402 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 14:36:46 -0300 Subject: A spawn names the pane it was made for, so a pane closed and its slot retaken spawns nothing The spawn effect carried only a slot, and the host read the command and shell off whatever pane held the slot as it forked: a command pane closed and its slot taken by the next one before the effects ran forked the new pane's command twice. The effect now carries the pane's serial and is dropped when the slot holds another; forkShell checks it again after giving up the turn for its directory's stat, the one moment a 9P client can change the panes under it. Every front end performs spawns with the turn, from its step. Co-Authored-By: Claude Opus 5.5 --- src/exec.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/exec.zig') diff --git a/src/exec.zig b/src/exec.zig index e2b9f880..86adfeeb 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -430,7 +430,7 @@ fn runCommand(p: *Pardes, from: usize, line: []const u8) ?usize { var buf: [command_max + 8]u8 = undefined; const lead = if (panes.Terminal.gridCursor(pane).x != 0) "\r\n" else ""; panes.Terminal.feedOutput(p, pane, std.fmt.bufPrint(&buf, "{s}% {s}\r\n", .{ lead, line }) catch "%\r\n"); - p.emit(.{ .spawn = .{ .pane = @intCast(id), .cwd = .from(pane.cwdSlice()) } }); + p.emit(.{ .spawn = .{ .pane = @intCast(id), .serial = pane.serial, .cwd = .from(pane.cwdSlice()) } }); noteRun(p, pane, "run", line); return id; } -- cgit v1.3