authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-23 13:12:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-24 23:53:46+02:00
log2a03d6b007163fbd83567a6b0907a1866c1f92e8
tree38e5bfa39a1abf905a7daba9f871be9d157dd421
parentd037c6c19d2021001ecf20884a4219aec88f151a

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

5 files changed, 29 insertions(+), 10 deletions(-)

lib/compiler/Maker.zig+2-1
......@@ -2674,7 +2674,8 @@ fn makeSteps(
26742674
26752675fn deinit(maker: *Maker) void {
26762676 const gpa = maker.gpa;
2677 for (maker.steps) |*step| step.deinit(gpa);
2677 const io = maker.graph.io;
2678 for (maker.steps) |*step| step.deinit(gpa, io);
26782679 maker.memory_blocked_steps.deinit(gpa);
26792680 maker.initial_steps.deinit(gpa);
26802681 maker.step_stack.deinit(gpa);
lib/compiler/Maker/Step.zig+16-7
......@@ -309,15 +309,13 @@ pub fn make(
309309 }
310310}
311311
312pub fn deinit(step: *Step, gpa: Allocator) void {
312pub fn deinit(step: *Step, gpa: Allocator, io: Io) void {
313313 step.clearResultStderr(gpa);
314314 step.clearFailedCommand(gpa);
315315 step.clearErrorBundle(gpa);
316316 step.inputs.deinit(gpa);
317 if (step.getZigProcess()) |zp| gpa.destroy(zp);
318317 switch (step.extended) {
319318 .check_file,
320 .compile,
321319 .config_header,
322320 .fail,
323321 .find_program,
......@@ -331,7 +329,7 @@ pub fn deinit(step: *Step, gpa: Allocator) void {
331329 .update_source_files,
332330 .write_file,
333331 => {},
334 inline .fmt, .run => |*extended| extended.deinit(gpa),
332 inline .compile, .fmt, .run => |*extended| extended.deinit(gpa, io),
335333 }
336334 step.* = undefined;
337335}
......@@ -455,6 +453,11 @@ pub const ZigProcess = struct {
455453 zp.multi_reader.deinit();
456454 zp.* = undefined;
457455 }
456
457 pub fn destroy(zp: *ZigProcess, gpa: Allocator, io: Io) void {
458 zp.deinit(io);
459 gpa.destroy(zp);
460 }
458461};
459462
460463/// Assumes that argv contains `--listen=-` and that the process being spawned
......@@ -482,9 +485,8 @@ pub fn evalZigProcess(
482485 zp.progress_ipc_index = null;
483486 var exited = false;
484487 defer if (exited) {
485 s.extended.compile.zig_process = null;
486 zp.deinit(io);
487 gpa.destroy(zp);
488 s.clearZigProcess();
489 zp.destroy(gpa, io);
488490 } else zp.saveState(prog_node);
489491 const result = zigProcessUpdate(step_index, maker, zp, watch) catch |err| switch (err) {
490492 error.BrokenPipe, error.EndOfStream => |reason| {
......@@ -730,6 +732,13 @@ pub fn getZigProcess(s: *Step) ?*ZigProcess {
730732 };
731733}
732734
735fn clearZigProcess(s: *Step) void {
736 (switch (s.extended) {
737 .compile => |*compile| &compile.zig_process,
738 else => return,
739 }).* = null;
740}
741
733742fn sendMessage(io: Io, file: Io.File, tag: std.zig.Client.Message.Tag) !void {
734743 const header: std.zig.Client.Message.Header = .{
735744 .tag = tag,
lib/compiler/Maker/Step/Compile.zig+7
......@@ -86,6 +86,13 @@ pub fn make(
8686 }
8787}
8888
89pub fn deinit(compile: *Compile, gpa: Allocator, io: Io) void {
90 if (compile.zig_process) |zp| {
91 zp.destroy(gpa, io);
92 compile.zig_process = null;
93 }
94}
95
8996fn updateGeneratedFile(
9097 maker: *Maker,
9198 arena: Allocator,
lib/compiler/Maker/Step/Fmt.zig+2-1
......@@ -64,6 +64,7 @@ pub fn make(
6464 try step.handleChildProcessTerm(maker, run_result.term);
6565}
6666
67pub fn deinit(fmt: *Fmt, gpa: std.mem.Allocator) void {
67pub fn deinit(fmt: *Fmt, gpa: std.mem.Allocator, io: std.Io) void {
68 _ = io;
6869 fmt.argv.deinit(gpa);
6970}
lib/compiler/Maker/Step/Run.zig+2-1
......@@ -372,7 +372,8 @@ pub fn make(
372372 step.clearFailedCommand(gpa);
373373}
374374
375pub fn deinit(run: *Run, gpa: Allocator) void {
375pub fn deinit(run: *Run, gpa: Allocator, io: Io) void {
376 _ = io;
376377 run.fuzz_tests.deinit(gpa);
377378}
378379