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,...@@ -63,9 +63,9 @@ protocol_server_mutex: Io.Mutex,
63web_server: ?*AvoidableWebServer,63web_server: ?*AvoidableWebServer,
64/// Allocated into `gpa`.64/// Allocated into `gpa`.
65memory_blocked_steps: std.ArrayList(Configuration.Step.Index),65memory_blocked_steps: std.ArrayList(Configuration.Step.Index),
66/// Allocated into `gpa`.66/// Allocated into `gpa` during `prepare`.
67initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void),67initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void),
68/// Allocated into `gpa`.68/// Allocated into `gpa` during `prepare`.
69step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void),69step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void),
70pkg_config: PkgConfig,70pkg_config: PkgConfig,
7171
...@@ -762,10 +762,8 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -762,10 +762,8 @@ pub fn main(init: process.Init.Minimal) !void {
762 .include = install_include_path,762 .include = install_include_path,
763 },763 },
764764
765 // Extra step at the end which is the autogenerated placeholder765 .steps = &.{},
766 // step which indicates that we need to reconfigure.766 .generated_files = &.{},
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),
769 .run_args = run_args,767 .run_args = run_args,
770768
771 .available_rss = max_rss,769 .available_rss = max_rss,
...@@ -792,11 +790,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -792,11 +790,7 @@ pub fn main(init: process.Init.Minimal) !void {
792 else790 else
793 .failures,791 .failures,
794 };792 };
795 defer {793 defer maker.deinit();
796 maker.memory_blocked_steps.deinit(gpa);
797 maker.initial_steps.deinit(gpa);
798 maker.step_stack.deinit(gpa);
799 }
800794
801 if (maker.available_rss == 0) {795 if (maker.available_rss == 0) {
802 maker.available_rss = process.totalSystemMemory() catch std.math.maxInt(u64);796 maker.available_rss = process.totalSystemMemory() catch std.math.maxInt(u64);
...@@ -863,6 +857,9 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -863,6 +857,9 @@ pub fn main(init: process.Init.Minimal) !void {
863 &watch.?,857 &watch.?,
864 if (in_debounce) .{ .ms = debounce_interval_ms } else .none,858 if (in_debounce) .{ .ms = debounce_interval_ms } else .none,
865 });859 });
860 } else if (watch) |*w| {
861 w.deinit();
862 watch = null;
866 }863 }
867864
868 continue :loop try select.await();865 continue :loop try select.await();
...@@ -915,7 +912,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -915,7 +912,7 @@ pub fn main(init: process.Init.Minimal) !void {
915 if (!Watch.have_impl) fatal("--watch not yet implemented for {t}", .{native_os});912 if (!Watch.have_impl) fatal("--watch not yet implemented for {t}", .{native_os});
916 break :w try .init(&maker);913 break :w try .init(&maker);
917 };914 };
918 defer w.deinit();915 defer if (watch_flag) w.deinit();
919916
920 if (web_server) |ws| try ws.updateConfiguration(&maker);917 if (web_server) |ws| try ws.updateConfiguration(&maker);
921918
...@@ -2229,6 +2226,11 @@ fn prepare(...@@ -2229,6 +2226,11 @@ fn prepare(
2229 const step_stack = &maker.step_stack;2226 const step_stack = &maker.step_stack;
2230 const c = &maker.scanned_config.configuration;2227 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
2232 // The last element is a reserved special pseudostep which contains the2234 // The last element is a reserved special pseudostep which contains the
2233 // watch inputs for the configurer executable.2235 // watch inputs for the configurer executable.
2234 for (maker.steps[0 .. maker.steps.len - 1], 0..) |*step, step_index_usize| {2236 for (maker.steps[0 .. maker.steps.len - 1], 0..) |*step, step_index_usize| {
...@@ -2549,7 +2551,7 @@ fn makeSteps(...@@ -2549,7 +2551,7 @@ fn makeSteps(
2549 };2551 };
2550 if (code == 0) {2552 if (code == 0) {
2551 removePoisonedConfiguration(io, maker.scanned_config);2553 removePoisonedConfiguration(io, maker.scanned_config);
2552 if (debugMakerLeaks()) return deinit(maker);2554 if (debugMakerLeaks()) return;
2553 }2555 }
2554 cleanup_task.await(io); // There is a defer above but an exit below.2556 cleanup_task.await(io); // There is a defer above but an exit below.
2555 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};2557 _ = io.lockStderr(&.{}, graph.stderr_mode) catch {};
...@@ -2558,12 +2560,10 @@ fn makeSteps(...@@ -2558,12 +2560,10 @@ fn makeSteps(
25582560
2559fn deinit(maker: *Maker) void {2561fn deinit(maker: *Maker) void {
2560 const gpa = maker.gpa;2562 const gpa = maker.gpa;
2561 for (maker.steps) |*step| {2563 for (maker.steps) |*step| step.deinit(gpa);
2562 step.clearResultStderr(gpa);2564 maker.memory_blocked_steps.deinit(gpa);
2563 step.clearFailedCommand(gpa);2565 maker.initial_steps.deinit(gpa);
2564 step.clearErrorBundle(gpa);2566 maker.step_stack.deinit(gpa);
2565 step.inputs.deinit(gpa);
2566 }
2567}2567}
25682568
2569fn stepReady(2569fn stepReady(
lib/compiler/Maker/Step.zig+9
...@@ -309,6 +309,15 @@ pub fn make(...@@ -309,6 +309,15 @@ pub fn make(
309 }309 }
310}310}
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
312/// Prepares the step for being re-evaluated.321/// Prepares the step for being re-evaluated.
313pub fn reset(step: *Step, maker: *Maker) void {322pub fn reset(step: *Step, maker: *Maker) void {
314 assert(step.state == .precheck_done);323 assert(step.state == .precheck_done);