summaryrefslogtreecommitdiff
path: root/src/detached
diff options
context:
space:
mode:
Diffstat (limited to 'src/detached')
-rw-r--r--src/detached/server.zig18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/detached/server.zig b/src/detached/server.zig
index a08a0342..676b5b95 100644
--- a/src/detached/server.zig
+++ b/src/detached/server.zig
@@ -485,9 +485,11 @@ pub const Session = struct {
fn spawn(ctx: ?*anyopaque, pane: u8, cwd: []const u8) void {
const s = of(ctx);
if (pane >= s.ptys.len) return; // the core indexes its own panes
- s.closePty(pane);
s.harvest();
- if (s.ptys[pane].pid != 0) return s.core.reportError(pane, "shell", error.ShellClosing);
+ // The new shell starts before a running one goes: one that cannot
+ // start leaves the running one be (pty/ctl's exec).
+ const running = s.ptys[pane].fd >= 0;
+ if (!running and s.ptys[pane].pid != 0) return s.core.reportError(pane, "shell", error.ShellClosing);
for (s.retired_shells) |shell| {
if (shell.pid == 0) break;
} else return s.core.reportError(pane, "shell", error.ShellClosing);
@@ -500,7 +502,17 @@ pub const Session = struct {
s.core.screen_h,
s.core.screen_w,
s.ninep,
- ) catch |err| return s.core.shellFailed(pane, err);
+ ) catch |err| {
+ if (running) return s.core.restartFailed(pane, err);
+ return s.core.shellFailed(pane, err);
+ };
+ s.closePty(pane);
+ s.harvest();
+ if (s.ptys[pane].pid != 0) {
+ _ = libc.close(child.file.handle);
+ host_io.retireShell(child.pid);
+ return s.core.reportError(pane, "shell", error.ShellClosing);
+ }
const command = if (s.core.panes[pane]) |pn| pn.command != null else false;
s.ptys[pane] = .{ .fd = child.file.handle, .pid = child.pid, .cmd = .{ .watched = command and host_io.watchExit(child.pid), .fd = child.file.handle } };
setNonblock(child.file.handle);