build: don't hang when capturing Stdout of verbose Build.Step.Run

When using Build.Step.Run.captureStdOut with a program that prints more
than 10 megabytes of output, the build process hangs.

This is because evalGeneric returns an error without reading child's
stdin till the end, so we subsequently get stuck in `try child.wait()`.

To fix this, make sure to kill the child in case of an error!

Output before this change:

    λ ./zig/zig build  -Dmultiversion=0.15.6 -Dconfig-release=0.15.7 -Dconfig-release-client-min=0.15.6
    [3/8] steps
    └─ run gh
    ^C
    λ # an hour of debugging

Output after this change:

    λ ./zig/zig build  -Dmultiversion=0.15.6 -Dconfig-release=0.15.7 -Dconfig-release-client-min=0.15.6
    install
    └─ install generated to ../tigerbeetle
       └─ run build_mutliversion (tigerbeetle)
          └─ run unzip
             └─ run gh failure
    error: unable to spawn gh: StdoutStreamTooLong
    Build Summary: 3/8 steps succeeded; 1 failed (disable with --summary none)
    install transitive failure
    └─ install generated to ../tigerbeetle transitive failure
       └─ run build_mutliversion (tigerbeetle) transitive failure
          └─ run unzip transitive failure
             └─ run gh failure
    error: the following build command failed with exit code 1:
    /home/matklad/p/tb/work/.zig-cache/o/c0e3f5e66ff441cd16f9a1a7e1401494/build /home/matklad/p/tb/work/zig/zig /home/matklad/p/tb/work /home/matklad/p/tb/work/.zig-cache /home/matklad/.cache/zig --seed 0xc1d4efc8 -Zaecc61299ff08765 -Dmultiversion=0.15.6 -Dconfig-release=0.15.7 -Dconfig-release-client-min=0.15.6
This commit is contained in:
Alex Kladov 2024-08-20 17:34:20 +01:00
parent 0a70455095
commit 8ae526b065

View File

@ -1369,18 +1369,22 @@ fn spawnChildAndCollect(
defer if (inherit) std.debug.unlockStdErr();
try child.spawn();
errdefer {
_ = child.kill() catch {};
}
var timer = try std.time.Timer.start();
const result = if (run.stdio == .zig_test)
evalZigTest(run, &child, prog_node, fuzz_context)
try evalZigTest(run, &child, prog_node, fuzz_context)
else
evalGeneric(run, &child);
try evalGeneric(run, &child);
break :t .{ try child.wait(), result, timer.read() };
};
return .{
.stdio = try result,
.stdio = result,
.term = term,
.elapsed_ns = elapsed_ns,
.peak_rss = child.resource_usage_statistics.getMaxRss() orelse 0,