diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 11:26:42 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:16 -0300 |
| commit | 0e6501ce210481c095e6f70a27e7f125f7af3761 (patch) | |
| tree | 0abf4b55e8eb4f836a3ad10963cbefd94efb8599 /src/ninep | |
| parent | 1ac8fbeedaf7cba881a7423b92ead1f739b8ac21 (diff) | |
| download | pardes-0e6501ce210481c095e6f70a27e7f125f7af3761.tar.gz pardes-0e6501ce210481c095e6f70a27e7f125f7af3761.zip | |
A pty/ctl exec that cannot start its shell keeps the one running
Each host closed the running shell before it forked the new one, so an exec whose shell failed left the pane with none and later runs answered error shell gone. A shell not there is now refused up front, and every host starts the new shell first, replacing the old only once the close-on-exec pipe says it ran; a failure there is only said (restartFailed).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep')
| -rw-r--r-- | src/ninep/ctl.zig | 16 | ||||
| -rw-r--r-- | src/ninep/pty.zig | 8 |
2 files changed, 23 insertions, 1 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 31382279..92342525 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -1996,7 +1996,7 @@ test "pty/ctl exec in a directory that is gone fails ENOENT; a shell that cannot try testing.expectEqualStrings("shell: access denied", p.fs.late_failure[0..p.fs.late_failure_len]); } -test "a script whose interpreter is not there: Tty refuses it up front, only an err logged" { +test "a script whose interpreter is not there: Tty refuses it up front, only an err logged, and pty/ctl exec keeps the running shell" { const p = try th.withTerm(testing.allocator); defer p.deinit(); const Starting = struct { @@ -2023,6 +2023,20 @@ test "a script whose interpreter is not there: Tty refuses it up front, only an try testing.expect(th.logHas(p, "Tty: interpreter /no/such/interp not found\n")); try testing.expect(!th.logHas(p, "\nmsg ")); try testing.expect(!th.logHas(p, "\ndel ")); + // The shell to start again is that script: refused before the running + // one goes. + const id = p.paneBySerial(serial).?; + p.panes[id].?.shell = try p.gpa.dupe(u8, try std.fmt.bufPrint(&line, "{s}/bad", .{dir})); + p.setCwd(id, dir); + const exec_refused = wr(p, Node.of(serial, .pty_ctl), "exec\n"); + try testing.expectEqual(E.NOENT, exec_refused.errno()); + try testing.expectEqualStrings("exec: interpreter /no/such/interp not found", exec_refused.reply.ename); + // One the host found could not start (the script changed after): said + // with the interpreter's name, and the running shell is not gone. + p.fs.late_failure_len = 0; + p.restartFailed(@intCast(id), error.InterpreterNotFound); + try testing.expectEqualStrings("shell: interpreter /no/such/interp not found", p.fs.late_failure[0..p.fs.late_failure_len]); + try testing.expect(!p.panes[id].?.shell_failed); } test "every EINVAL a write gets says why, in its err record too; DEL is a control character in a line" { diff --git a/src/ninep/pty.zig b/src/ninep/pty.zig index aa0f499a..bf5f432c 100644 --- a/src/ninep/pty.zig +++ b/src/ninep/pty.zig @@ -67,6 +67,14 @@ pub fn writeCtl(p: *Pardes, req: Req, id: usize) Reply { const dir = pane.cwdSlice(); return tree.failText(req.tag, E.NOENT, std.fmt.bufPrint(&p.fs.ename, "exec: {s}: no such directory", .{dir[0..@min(dir.len, 256)]}) catch "exec: no such directory"); }; + // Nor is a shell that is not there, or a script whose + // interpreter is not: refused, and the running shell kept. + if (comptime pardes.hosted) if (!apply and std.mem.eql(u8, line, "exec")) if (p.panes[id]) |pane| { + const bin = pane.shell orelse p.shellBin(); + var why: [320]u8 = undefined; + if (@import("../host_io.zig").Shell.refusal(bin[0..@min(bin.len, 200)], &why)) |refused| + return tree.failText(req.tag, E.NOENT, std.fmt.bufPrint(&p.fs.ename, "exec: {s}", .{refused}) catch "exec: no such shell"); + }; if (!verb(p, id, line, apply)) return tree.failText(req.tag, E.INVAL, if (outOfRange(line)) e_winsize_range else e_bad_pty_ctl); } } |
