fix: proactive close subprocesses on early exit in shell module

This commit is contained in:
CJ van den Berg 2025-04-23 18:30:49 +02:00
parent 2aba314e08
commit 0fb10e3aa5
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9

View file

@ -169,20 +169,25 @@ const Process = struct {
} }
fn deinit(self: *Process) void { fn deinit(self: *Process) void {
if (self.sp) |*sp| sp.deinit(); if (self.sp) |*sp| {
defer self.sp = null;
sp.deinit();
}
self.parent.deinit(); self.parent.deinit();
self.logger.deinit(); self.logger.deinit();
self.allocator.free(self.arg0); self.allocator.free(self.arg0);
self.allocator.free(self.argv.buf); self.allocator.free(self.argv.buf);
self.close() catch {};
self.allocator.destroy(self); self.allocator.destroy(self);
} }
fn close(self: *Process) tp.result { fn close(self: *Process) void {
if (self.sp) |*sp| { defer self.sp = null;
defer self.sp = null; if (self.sp) |*sp| sp.close() catch {};
try sp.close(); }
}
fn term(self: *Process) void {
defer self.sp = null;
if (self.sp) |*sp| sp.term() catch {};
} }
fn start(self: *Process) tp.result { fn start(self: *Process) tp.result {
@ -204,14 +209,17 @@ const Process = struct {
const sp = self.sp orelse return tp.exit_error(error.Closed, null); const sp = self.sp orelse return tp.exit_error(error.Closed, null);
try sp.send(bytes); try sp.send(bytes);
} else if (try m.match(.{"close"})) { } else if (try m.match(.{"close"})) {
try self.close(); self.close();
} else if (try m.match(.{ module_name, "stdout", tp.extract(&bytes) })) { } else if (try m.match(.{ module_name, "stdout", tp.extract(&bytes) })) {
self.handlers.out(self.handlers.context, self.parent.ref(), self.arg0, bytes); self.handlers.out(self.handlers.context, self.parent.ref(), self.arg0, bytes);
} else if (try m.match(.{ module_name, "stderr", tp.extract(&bytes) })) { } else if (try m.match(.{ module_name, "stderr", tp.extract(&bytes) })) {
(self.handlers.err orelse self.handlers.out)(self.handlers.context, self.parent.ref(), self.arg0, bytes); (self.handlers.err orelse self.handlers.out)(self.handlers.context, self.parent.ref(), self.arg0, bytes);
} else if (try m.match(.{ module_name, "term", tp.more })) { } else if (try m.match(.{ module_name, "term", tp.more })) {
defer self.sp = null;
self.handle_terminated(m) catch |e| return tp.exit_error(e, @errorReturnTrace()); self.handle_terminated(m) catch |e| return tp.exit_error(e, @errorReturnTrace());
return tp.exit_normal();
} else if (try m.match(.{ "exit", "normal" })) { } else if (try m.match(.{ "exit", "normal" })) {
self.term();
return tp.exit_normal(); return tp.exit_normal();
} else { } else {
self.logger.err("receive", tp.unexpected(m)); self.logger.err("receive", tp.unexpected(m));