diff options
Diffstat (limited to 'src/detached/server.zig')
| -rw-r--r-- | src/detached/server.zig | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/detached/server.zig b/src/detached/server.zig index a3694c57..0cf1729f 100644 --- a/src/detached/server.zig +++ b/src/detached/server.zig @@ -351,6 +351,7 @@ pub const Session = struct { .pty_write = ptyWrite, .pty_resize = ptyResize, .pty_signal = ptySignal, + .close_pty = closePaneShell, .tty_taken = ttyTaken, .write_file = writeFile, .write_dump = writeDump, @@ -606,6 +607,11 @@ pub const Session = struct { } } + fn closePaneShell(ctx: ?*anyopaque, pane: u8) void { + const s = of(ctx); + if (pane < s.ptys.len) s.closePty(pane); + } + fn closePty(s: *Session, pane: u8) void { const pt = &s.ptys[pane]; if (pt.fd < 0) return; @@ -1229,6 +1235,44 @@ test "detached queued results preserve current requests and are discarded before try std.testing.expect(s.core.lsp_wait == null); } +test "a detached session's terminal pane takes its shell with it when it closes" { + const gpa = std.testing.allocator; + var s: Session = .{ + .gpa = gpa, + .worker_gpa = gpa, + .io = std.testing.io, + .core = try pardes.Pardes.init(gpa, .{ .tty_only = true, .cols = 40, .rows = 12 }), + .cols = 40, + .rows = 12, + }; + defer s.core.deinit(); + defer s.deinit(); + // A stand-in shell: it waits for a signal, and a hangup ends it. + const pid = libc.fork(); + if (pid == 0) while (true) { + _ = libc.poll(&[0]libc.pollfd{}, 0, -1); + }; + try std.testing.expect(pid > 0); + var fds: [2]c_int = undefined; + try std.testing.expectEqual(@as(c_int, 0), libc.pipe(&fds)); + defer _ = libc.close(fds[1]); + s.ptys[3] = .{ .fd = fds[0], .pid = pid }; + const host = s.host(); + host.vtable.close_pty.?(host.ctx, 3); + try std.testing.expect(s.ptys[3].fd < 0); + const deadline = monotonicMs() + 2000; + while (monotonicMs() < deadline) { + s.harvest(); + const running = s.ptys[3].pid != 0 or for (s.retired_shells) |shell| { + if (shell.pid == pid) break true; + } else false; + if (!running) break; + _ = libc.poll(&[0]libc.pollfd{}, 0, 5); + } + try std.testing.expect(s.ptys[3].pid == 0); + for (s.retired_shells) |shell| try std.testing.expect(shell.pid != pid); +} + test "detached worker setup failure completes requests without changing document bytes" { const gpa = std.testing.allocator; var failing = std.testing.FailingAllocator.init(gpa, .{ .fail_index = 0 }); |
