From 2a03d6b007163fbd83567a6b0907a1866c1f92e8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 23 Sep 2026 13:12:16 -0700 Subject: [PATCH] Maker: properly deinit compiler child procs Problem was that when Maker.Step.Compile was deinitialized, it would reap the memory for the child process, but not actually kill & wait for the termination of the process. Leaving the extra processes running caused "Reusing Cache Artifacts" deadlocks, not to mention wasting resources. closes #36513 --- lib/compiler/Maker.zig | 3 ++- lib/compiler/Maker/Step.zig | 23 ++++++++++++++++------- lib/compiler/Maker/Step/Compile.zig | 7 +++++++ lib/compiler/Maker/Step/Fmt.zig | 3 ++- lib/compiler/Maker/Step/Run.zig | 3 ++- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig index 05ce0fe17e64c265e5c2e87226362308a770a9d0..681a91341b99cdaa0a837d783f974924a036f803 100644 --- a/lib/compiler/Maker.zig +++ b/lib/compiler/Maker.zig @@ -2674,7 +2674,8 @@ fn makeSteps( fn deinit(maker: *Maker) void { const gpa = maker.gpa; - for (maker.steps) |*step| step.deinit(gpa); + const io = maker.graph.io; + for (maker.steps) |*step| step.deinit(gpa, io); maker.memory_blocked_steps.deinit(gpa); maker.initial_steps.deinit(gpa); maker.step_stack.deinit(gpa); diff --git a/lib/compiler/Maker/Step.zig b/lib/compiler/Maker/Step.zig index 8496548b7a8970292533c1fca07ff58cc2b265aa..fc1b7f5b324659d8381a7bcbe9d1be7b567cea41 100644 --- a/lib/compiler/Maker/Step.zig +++ b/lib/compiler/Maker/Step.zig @@ -309,15 +309,13 @@ pub fn make( } } -pub fn deinit(step: *Step, gpa: Allocator) void { +pub fn deinit(step: *Step, gpa: Allocator, io: Io) void { step.clearResultStderr(gpa); step.clearFailedCommand(gpa); step.clearErrorBundle(gpa); step.inputs.deinit(gpa); - if (step.getZigProcess()) |zp| gpa.destroy(zp); switch (step.extended) { .check_file, - .compile, .config_header, .fail, .find_program, @@ -331,7 +329,7 @@ pub fn deinit(step: *Step, gpa: Allocator) void { .update_source_files, .write_file, => {}, - inline .fmt, .run => |*extended| extended.deinit(gpa), + inline .compile, .fmt, .run => |*extended| extended.deinit(gpa, io), } step.* = undefined; } @@ -455,6 +453,11 @@ pub const ZigProcess = struct { zp.multi_reader.deinit(); zp.* = undefined; } + + pub fn destroy(zp: *ZigProcess, gpa: Allocator, io: Io) void { + zp.deinit(io); + gpa.destroy(zp); + } }; /// Assumes that argv contains `--listen=-` and that the process being spawned @@ -482,9 +485,8 @@ pub fn evalZigProcess( zp.progress_ipc_index = null; var exited = false; defer if (exited) { - s.extended.compile.zig_process = null; - zp.deinit(io); - gpa.destroy(zp); + s.clearZigProcess(); + zp.destroy(gpa, io); } else zp.saveState(prog_node); const result = zigProcessUpdate(step_index, maker, zp, watch) catch |err| switch (err) { error.BrokenPipe, error.EndOfStream => |reason| { @@ -730,6 +732,13 @@ pub fn getZigProcess(s: *Step) ?*ZigProcess { }; } +fn clearZigProcess(s: *Step) void { + (switch (s.extended) { + .compile => |*compile| &compile.zig_process, + else => return, + }).* = null; +} + fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void { const header: std.zig.Client.Message.Header = .{ .tag = tag, diff --git a/lib/compiler/Maker/Step/Compile.zig b/lib/compiler/Maker/Step/Compile.zig index cd144b077fbc250136b75b9b4511cbf110bd5c16..2e02f3407b6bfbbc4034eb6570732fe26b91271a 100644 --- a/lib/compiler/Maker/Step/Compile.zig +++ b/lib/compiler/Maker/Step/Compile.zig @@ -86,6 +86,13 @@ pub fn make( } } +pub fn deinit(compile: *Compile, gpa: Allocator, io: Io) void { + if (compile.zig_process) |zp| { + zp.destroy(gpa, io); + compile.zig_process = null; + } +} + fn updateGeneratedFile( maker: *Maker, arena: Allocator, diff --git a/lib/compiler/Maker/Step/Fmt.zig b/lib/compiler/Maker/Step/Fmt.zig index 72267c6e9fedeef3707e5e14b681c87d7636bf4e..d936382bdf7d54012b86f714adc1b67758d453c8 100644 --- a/lib/compiler/Maker/Step/Fmt.zig +++ b/lib/compiler/Maker/Step/Fmt.zig @@ -64,6 +64,7 @@ pub fn make( try step.handleChildProcessTerm(maker, run_result.term); } -pub fn deinit(fmt: *Fmt, gpa: std.mem.Allocator) void { +pub fn deinit(fmt: *Fmt, gpa: std.mem.Allocator, io: std.Io) void { + _ = io; fmt.argv.deinit(gpa); } diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig index a31694851d1793008a30e0b159ce2a75a47d497b..7421d579ad8129e56515e90c16fdf7d1d9593e14 100644 --- a/lib/compiler/Maker/Step/Run.zig +++ b/lib/compiler/Maker/Step/Run.zig @@ -372,7 +372,8 @@ pub fn make( step.clearFailedCommand(gpa); } -pub fn deinit(run: *Run, gpa: Allocator) void { +pub fn deinit(run: *Run, gpa: Allocator, io: Io) void { + _ = io; run.fuzz_tests.deinit(gpa); } -- 2.54.0