fix(terminal): properly catch child EOF
And be much more explicit about error handling.
This commit is contained in:
parent
61a509cf2f
commit
69b0885f4b
2 changed files with 54 additions and 20 deletions
|
|
@ -30,8 +30,8 @@
|
||||||
.hash = "fuzzig-0.1.1-Ji0xivxIAQBD0g8O_NV_0foqoPf3elsg9Sc3pNfdVH4D",
|
.hash = "fuzzig-0.1.1-Ji0xivxIAQBD0g8O_NV_0foqoPf3elsg9Sc3pNfdVH4D",
|
||||||
},
|
},
|
||||||
.vaxis = .{
|
.vaxis = .{
|
||||||
.url = "git+https://github.com/neurocyte/libvaxis?ref=main#03fe1b123afdaf879829da507f54e42780d4ec65",
|
.url = "git+https://github.com/neurocyte/libvaxis?ref=main#8fba2b2b14174f73a957b3b4b0e1c30f25a78577",
|
||||||
.hash = "vaxis-0.5.1-BWNV_EJOCQCOD5tzfVqOgDUSYfvBLrokxE0fr9MSb05q",
|
.hash = "vaxis-0.5.1-BWNV_HJQCQAVq-jmKeSh0Ur4DLbkc3DUP-amXI3k22TB",
|
||||||
},
|
},
|
||||||
.zeit = .{
|
.zeit = .{
|
||||||
.url = "git+https://github.com/rockorager/zeit?ref=zig-0.15#ed2ca60db118414bda2b12df2039e33bad3b0b88",
|
.url = "git+https://github.com/rockorager/zeit?ref=zig-0.15#ed2ca60db118414bda2b12df2039e33bad3b0b88",
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ const Vt = struct {
|
||||||
self.cwd.deinit(allocator);
|
self.cwd.deinit(allocator);
|
||||||
self.title.deinit(allocator);
|
self.title.deinit(allocator);
|
||||||
if (self.pty_pid) |pid| {
|
if (self.pty_pid) |pid| {
|
||||||
pid.send(.{ "pty_actor", "quit" }) catch {};
|
pid.send(.{"quit"}) catch {};
|
||||||
pid.deinit();
|
pid.deinit();
|
||||||
self.pty_pid = null;
|
self.pty_pid = null;
|
||||||
}
|
}
|
||||||
|
|
@ -340,16 +340,20 @@ const pty = struct {
|
||||||
errdefer self.deinit();
|
errdefer self.deinit();
|
||||||
|
|
||||||
if (try m.match(.{ "fd", "pty", "read_ready" })) {
|
if (try m.match(.{ "fd", "pty", "read_ready" })) {
|
||||||
try self.read_and_process();
|
self.read_and_process() catch |e| return switch (e) {
|
||||||
return;
|
error.Terminated => tp.exit_normal(),
|
||||||
}
|
error.InputOutput => tp.exit_normal(),
|
||||||
|
error.SendFailed => tp.exit_normal(),
|
||||||
if (try m.match(.{ "pty_actor", "quit" })) {
|
error.Unexpected => tp.exit_normal(),
|
||||||
|
};
|
||||||
|
} else if (try m.match(.{"quit"})) {
|
||||||
return tp.exit_normal();
|
return tp.exit_normal();
|
||||||
|
} else {
|
||||||
|
return tp.unexpected(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_and_process(self: *@This()) tp.result {
|
fn read_and_process(self: *@This()) error{ Terminated, InputOutput, SendFailed, Unexpected }!void {
|
||||||
var buf: [4096]u8 = undefined;
|
var buf: [4096]u8 = undefined;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
@ -359,27 +363,57 @@ const pty = struct {
|
||||||
const code = self.vt.cmd.wait();
|
const code = self.vt.cmd.wait();
|
||||||
self.vt.event_queue.push(.{ .exited = code });
|
self.vt.event_queue.push(.{ .exited = code });
|
||||||
self.parent.send(.{ "terminal_view", "output" }) catch {};
|
self.parent.send(.{ "terminal_view", "output" }) catch {};
|
||||||
return tp.exit_normal();
|
return error.InputOutput;
|
||||||
|
},
|
||||||
|
error.SystemResources,
|
||||||
|
error.IsDir,
|
||||||
|
error.OperationAborted,
|
||||||
|
error.BrokenPipe,
|
||||||
|
error.ConnectionResetByPeer,
|
||||||
|
error.ConnectionTimedOut,
|
||||||
|
error.NotOpenForReading,
|
||||||
|
error.SocketNotConnected,
|
||||||
|
error.Canceled,
|
||||||
|
error.AccessDenied,
|
||||||
|
error.ProcessNotFound,
|
||||||
|
error.LockViolation,
|
||||||
|
error.Unexpected,
|
||||||
|
=> {
|
||||||
|
std.log.err("terminal_view: read unexpected: {}", .{e});
|
||||||
|
return error.Unexpected;
|
||||||
},
|
},
|
||||||
else => return tp.exit_error(e, @errorReturnTrace()),
|
|
||||||
};
|
};
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
const code = self.vt.cmd.wait();
|
const code = self.vt.cmd.wait();
|
||||||
self.vt.event_queue.push(.{ .exited = code });
|
self.vt.event_queue.push(.{ .exited = code });
|
||||||
self.parent.send(.{ "terminal_view", "output" }) catch {};
|
self.parent.send(.{ "terminal_view", "output" }) catch {};
|
||||||
return tp.exit_normal();
|
return error.Terminated;
|
||||||
}
|
}
|
||||||
|
|
||||||
const exited = self.vt.processOutput(&self.parser, buf[0..n]) catch |e|
|
defer self.parent.send(.{ "terminal_view", "output" }) catch {};
|
||||||
return tp.exit_error(e, @errorReturnTrace());
|
|
||||||
if (exited) {
|
switch (self.vt.processOutput(&self.parser, buf[0..n]) catch |e| switch (e) {
|
||||||
self.parent.send(.{ "terminal_view", "output" }) catch {};
|
error.WriteFailed,
|
||||||
return tp.exit_normal();
|
error.ReadFailed,
|
||||||
|
error.OutOfMemory,
|
||||||
|
error.Utf8InvalidStartByte,
|
||||||
|
=> {
|
||||||
|
std.log.err("terminal_view: processOutput unexpected: {}", .{e});
|
||||||
|
return error.Unexpected;
|
||||||
|
},
|
||||||
|
}) {
|
||||||
|
.exited => {
|
||||||
|
return error.Terminated;
|
||||||
|
},
|
||||||
|
.running => {},
|
||||||
}
|
}
|
||||||
// Notify parent that new output is available.
|
|
||||||
self.parent.send(.{ "terminal_view", "output" }) catch {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fd.wait_read() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
self.fd.wait_read() catch |e| switch (e) {
|
||||||
|
error.ThespianFileDescriptorWaitReadFailed => {
|
||||||
|
std.log.err("terminal_view: wait_read unexpected: {}", .{e});
|
||||||
|
return error.Unexpected;
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue