authorgravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2026-08-29 00:45:49+02:00
committergravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2026-08-29 00:45:49+02:00
log81be5b22a34424972c6b75201c510f5159f5d4f3
tree2becd70abd9550d2ba4c73c0f123a74fca48b80d
parent5926dd027df2f35d4ff3610c16cfcad8e0b3a4b5
signature Signed by SSH key SHA256:HYC3SjXQcAt6uwv9pu/6OoVQ2rUH8rb5zKiUHSe9uxk

Maker: fix leaks on process exit

Can be observed with `--debug-maker-leaks`.

2 files changed, 28 insertions(+), 19 deletions(-)

lib/compiler/Maker.zig+19-19
......@@ -63,9 +63,9 @@ protocol_server_mutex: Io.Mutex,
6363web_server: ?*AvoidableWebServer,
6464/// Allocated into `gpa`.
6565memory_blocked_steps: std.ArrayList(Configuration.Step.Index),
66/// Allocated into `gpa`.
66/// Allocated into `gpa` during `prepare`.
6767initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void),
68/// Allocated into `gpa`.
68/// Allocated into `gpa` during `prepare`.
6969step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void),
7070pkg_config: PkgConfig,
7171
......@@ -762,10 +762,8 @@ pub fn main(init: process.Init.Minimal) !void {
762762 .include = install_include_path,
763763 },
764764
765 // Extra step at the end which is the autogenerated placeholder
766 // step which indicates that we need to reconfigure.
767 .steps = try arena.alloc(Step, scanned_config.configuration.steps.len + 1),
768 .generated_files = try arena.alloc(Path, scanned_config.configuration.generated_files_len),
765 .steps = &.{},
766 .generated_files = &.{},
769767 .run_args = run_args,
770768
771769 .available_rss = max_rss,
......@@ -792,11 +790,7 @@ pub fn main(init: process.Init.Minimal) !void {
792790 else
793791 .failures,
794792 };
795 defer {
796 maker.memory_blocked_steps.deinit(gpa);
797 maker.initial_steps.deinit(gpa);
798 maker.step_stack.deinit(gpa);
799 }
793 defer maker.deinit();
800794
801795 if (maker.available_rss == 0) {
802796 maker.available_rss = process.totalSystemMemory() catch std.math.maxInt(u64);
......@@ -863,6 +857,9 @@ pub fn main(init: process.Init.Minimal) !void {
863857 &watch.?,
864858 if (in_debounce) .{ .ms = debounce_interval_ms } else .none,
865859 });
860 } else if (watch) |*w| {
861 w.deinit();
862 watch = null;
866863 }
867864
868865 continue :loop try select.await();
......@@ -915,7 +912,7 @@ pub fn main(init: process.Init.Minimal) !void {
915912 if (!Watch.have_impl) fatal("--watch not yet implemented for {t}", .{native_os});
916913 break :w try .init(&maker);
917914 };
918 defer w.deinit();
915 defer if (watch_flag) w.deinit();
919916
920917 if (web_server) |ws| try ws.updateConfiguration(&maker);
921918
......@@ -2229,6 +2226,11 @@ fn prepare(
22292226 const step_stack = &maker.step_stack;
22302227 const c = &maker.scanned_config.configuration;
22312228
2229 // Extra step at the end which is the autogenerated placeholder
2230 // step which indicates that we need to reconfigure.
2231 maker.steps = try arena.alloc(Step, c.steps.len + 1);
2232 maker.generated_files = try arena.alloc(Path, c.generated_files_len);
2233
22322234 // The last element is a reserved special pseudostep which contains the
22332235 // watch inputs for the configurer executable.
22342236 for (maker.steps[0 .. maker.steps.len - 1], 0..) |*step, step_index_usize| {
......@@ -2549,7 +2551,7 @@ fn makeSteps(
25492551 };
25502552 if (code == 0) {
25512553 removePoisonedConfiguration(io, maker.scanned_config);
2552 if (debugMakerLeaks()) return deinit(maker);
2554 if (debugMakerLeaks()) return;
25532555 }
25542556 cleanup_task.await(io); // There is a defer above but an exit below.
25552557 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
......@@ -2558,12 +2560,10 @@ fn makeSteps(
25582560
25592561fn deinit(maker: *Maker) void {
25602562 const gpa = maker.gpa;
2561 for (maker.steps) |*step| {
2562 step.clearResultStderr(gpa);
2563 step.clearFailedCommand(gpa);
2564 step.clearErrorBundle(gpa);
2565 step.inputs.deinit(gpa);
2566 }
2563 for (maker.steps) |*step| step.deinit(gpa);
2564 maker.memory_blocked_steps.deinit(gpa);
2565 maker.initial_steps.deinit(gpa);
2566 maker.step_stack.deinit(gpa);
25672567}
25682568
25692569fn stepReady(
lib/compiler/Maker/Step.zig+9
......@@ -309,6 +309,15 @@ pub fn make(
309309 }
310310}
311311
312pub fn deinit(step: *Step, gpa: Allocator) void {
313 step.clearResultStderr(gpa);
314 step.clearFailedCommand(gpa);
315 step.clearErrorBundle(gpa);
316 step.inputs.deinit(gpa);
317 if (step.getZigProcess()) |zp| gpa.destroy(zp);
318 step.* = undefined;
319}
320
312321/// Prepares the step for being re-evaluated.
313322pub fn reset(step: *Step, maker: *Maker) void {
314323 assert(step.state == .precheck_done);