From 9566a1a87eb04c85f7d9db5b62a138aa7e1a1879 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Thu, 20 Aug 2026 09:00:56 -0400 Subject: [PATCH] termio: release initial input resources Initial input files remained open and their fully read buffers remained allocated after queueWrite copied their contents. Close these files on both startup success and failure, free their contents after queueing, and borrow raw values already owned by the arena. --- src/termio/Termio.zig | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/termio/Termio.zig b/src/termio/Termio.zig index 7d6e179d8..0f8a7cc4d 100644 --- a/src/termio/Termio.zig +++ b/src/termio/Termio.zig @@ -119,13 +119,15 @@ const ThreadEnterState = struct { ) (Allocator.Error || error{InputNotFound})![]const Input { const alloc = self.arena.allocator(); - var input = try alloc.alloc( - Input, + var inputs: std.ArrayList(Input) = try .initCapacity( + alloc, self.input.list.items.len, ); - for (self.input.list.items, 0..) |item, i| { - input[i] = switch (item) { - .raw => |v| .{ .string = try alloc.dupe(u8, v) }, + errdefer for (inputs.items) |item| item.deinit(); + + for (self.input.list.items) |item| { + inputs.appendAssumeCapacity(switch (item) { + .raw => |v| .{ .string = v }, .path => |path| file: { const f = std.Io.Dir.cwd().openFile( global.io(), @@ -141,15 +143,22 @@ const ThreadEnterState = struct { break :file .{ .file = f }; }, - }; + }); } - return input; + return inputs.items; } const Input = union(enum) { string: []const u8, file: std.Io.File, + + fn deinit(self: Input) void { + switch (self) { + .string => {}, + .file => |f| f.close(global.io()), + } + } }; }; @@ -346,6 +355,9 @@ pub fn threadEnter( try v.prepareInput() else null; + defer if (inputs) |items| { + for (items) |input| input.deinit(); + }; data.* = .{ .alloc = self.alloc, @@ -366,20 +378,21 @@ pub fn threadEnter( log.warn("failed to queue input string err={}", .{err}); return error.InputFailed; }, - .file => |f| self.queueWrite( - data, - compat_file.readToEndAlloc( + .file => |f| { + const contents = compat_file.readToEndAlloc( f, self.alloc, 10 * 1024 * 1024, // 10 MiB max ) catch |err| { log.warn("failed to read input file err={}", .{err}); return error.InputFailed; - }, - false, - ) catch |err| { - log.warn("failed to queue input file err={}", .{err}); - return error.InputFailed; + }; + defer self.alloc.free(contents); + + self.queueWrite(data, contents, false) catch |err| { + log.warn("failed to queue input file err={}", .{err}); + return error.InputFailed; + }; }, }; }