authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-08 22:37:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-08 22:37:01-07:00
log7dd4afb224f4ca747b8eb462c28337ce9a63d38c
treee4e634ad79891ae089b7f02f417bf661824f6679
parent4592fd26b937d8c7ff91295408d8377c1c13cf53

stage2: link: properly implement passthrough mode for LLD child proc

passthrough mode does not mean always exit - it just means to pass through stdio and exit if the child process exits, without doing any special error reporting.

5 files changed, 193 insertions(+), 137 deletions(-)

src/Compilation.zig+1-1
......@@ -1804,7 +1804,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *
18041804 if (comp.clang_preprocessor_mode == .stdout)
18051805 std.process.exit(0);
18061806 },
1807 else => std.process.exit(1),
1807 else => std.process.abort(),
18081808 }
18091809 } else {
18101810 child.stdin_behavior = .Ignore;
src/link/Coff.zig+50-36
......@@ -1153,46 +1153,60 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
11531153 }
11541154
11551155 // Sadly, we must run LLD as a child process because it does not behave
1156 // properly as a library. One exception is if we are running in passthrough
1157 // mode, which means Clang / LLD should inherit stdio and are allowed to
1158 // crash zig directly.
1159 if (comp.clang_passthrough_mode) {
1160 return @import("../main.zig").punt_to_lld(arena, argv.items);
1161 }
1162
1156 // properly as a library.
11631157 const child = try std.ChildProcess.init(argv.items, arena);
11641158 defer child.deinit();
11651159
1166 child.stdin_behavior = .Ignore;
1167 child.stdout_behavior = .Ignore;
1168 child.stderr_behavior = .Pipe;
1169
1170 try child.spawn();
1171
1172 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
1173
1174 const term = child.wait() catch |err| {
1175 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1176 return error.UnableToSpawnSelf;
1177 };
1178
1179 switch (term) {
1180 .Exited => |code| {
1181 if (code != 0) {
1182 // TODO parse this output and surface with the Compilation API rather than
1183 // directly outputting to stderr here.
1184 std.debug.print("{s}", .{stderr});
1185 return error.LLDReportedFailure;
1186 }
1187 },
1188 else => {
1189 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
1190 return error.LLDCrashed;
1191 },
1192 }
1160 if (comp.clang_passthrough_mode) {
1161 child.stdin_behavior = .Inherit;
1162 child.stdout_behavior = .Inherit;
1163 child.stderr_behavior = .Inherit;
1164
1165 const term = child.spawnAndWait() catch |err| {
1166 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1167 return error.UnableToSpawnSelf;
1168 };
1169 switch (term) {
1170 .Exited => |code| {
1171 if (code != 0) {
1172 // TODO https://github.com/ziglang/zig/issues/6342
1173 std.process.exit(1);
1174 }
1175 },
1176 else => std.process.abort(),
1177 }
1178 } else {
1179 child.stdin_behavior = .Ignore;
1180 child.stdout_behavior = .Ignore;
1181 child.stderr_behavior = .Pipe;
1182
1183 try child.spawn();
1184
1185 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
1186
1187 const term = child.wait() catch |err| {
1188 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1189 return error.UnableToSpawnSelf;
1190 };
1191
1192 switch (term) {
1193 .Exited => |code| {
1194 if (code != 0) {
1195 // TODO parse this output and surface with the Compilation API rather than
1196 // directly outputting to stderr here.
1197 std.debug.print("{s}", .{stderr});
1198 return error.LLDReportedFailure;
1199 }
1200 },
1201 else => {
1202 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
1203 return error.LLDCrashed;
1204 },
1205 }
11931206
1194 if (stderr.len != 0) {
1195 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
1207 if (stderr.len != 0) {
1208 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
1209 }
11961210 }
11971211 }
11981212
src/link/Elf.zig+46-32
......@@ -1632,46 +1632,60 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
16321632 }
16331633
16341634 // Sadly, we must run LLD as a child process because it does not behave
1635 // properly as a library. One exception is if we are running in passthrough
1636 // mode, which means Clang / LLD should inherit stdio and are allowed to
1637 // crash zig directly.
1638 if (comp.clang_passthrough_mode) {
1639 return @import("../main.zig").punt_to_lld(arena, argv.items);
1640 }
1641
1635 // properly as a library.
16421636 const child = try std.ChildProcess.init(argv.items, arena);
16431637 defer child.deinit();
16441638
1645 child.stdin_behavior = .Ignore;
1646 child.stdout_behavior = .Ignore;
1647 child.stderr_behavior = .Pipe;
1639 if (comp.clang_passthrough_mode) {
1640 child.stdin_behavior = .Inherit;
1641 child.stdout_behavior = .Inherit;
1642 child.stderr_behavior = .Inherit;
16481643
1649 try child.spawn();
1644 const term = child.spawnAndWait() catch |err| {
1645 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1646 return error.UnableToSpawnSelf;
1647 };
1648 switch (term) {
1649 .Exited => |code| {
1650 if (code != 0) {
1651 // TODO https://github.com/ziglang/zig/issues/6342
1652 std.process.exit(1);
1653 }
1654 },
1655 else => std.process.abort(),
1656 }
1657 } else {
1658 child.stdin_behavior = .Ignore;
1659 child.stdout_behavior = .Ignore;
1660 child.stderr_behavior = .Pipe;
16501661
1651 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
1662 try child.spawn();
16521663
1653 const term = child.wait() catch |err| {
1654 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1655 return error.UnableToSpawnSelf;
1656 };
1664 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
16571665
1658 switch (term) {
1659 .Exited => |code| {
1660 if (code != 0) {
1661 // TODO parse this output and surface with the Compilation API rather than
1662 // directly outputting to stderr here.
1663 std.debug.print("{s}", .{stderr});
1664 return error.LLDReportedFailure;
1665 }
1666 },
1667 else => {
1668 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
1669 return error.LLDCrashed;
1670 },
1671 }
1666 const term = child.wait() catch |err| {
1667 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1668 return error.UnableToSpawnSelf;
1669 };
16721670
1673 if (stderr.len != 0) {
1674 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
1671 switch (term) {
1672 .Exited => |code| {
1673 if (code != 0) {
1674 // TODO parse this output and surface with the Compilation API rather than
1675 // directly outputting to stderr here.
1676 std.debug.print("{s}", .{stderr});
1677 return error.LLDReportedFailure;
1678 }
1679 },
1680 else => {
1681 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
1682 return error.LLDCrashed;
1683 },
1684 }
1685
1686 if (stderr.len != 0) {
1687 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
1688 }
16751689 }
16761690
16771691 if (!self.base.options.disable_lld_caching) {
src/link/MachO.zig+50-36
......@@ -686,46 +686,60 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
686686 }
687687 } else {
688688 // Sadly, we must run LLD as a child process because it does not behave
689 // properly as a library. One exception is if we are running in passthrough
690 // mode, which means Clang / LLD should inherit stdio and are allowed to
691 // crash zig directly.
692 if (comp.clang_passthrough_mode) {
693 return @import("../main.zig").punt_to_lld(arena, argv.items);
694 }
695
689 // properly as a library.
696690 const child = try std.ChildProcess.init(argv.items, arena);
697691 defer child.deinit();
698692
699 child.stdin_behavior = .Ignore;
700 child.stdout_behavior = .Ignore;
701 child.stderr_behavior = .Pipe;
702
703 try child.spawn();
704
705 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
706
707 const term = child.wait() catch |err| {
708 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
709 return error.UnableToSpawnSelf;
710 };
711
712 switch (term) {
713 .Exited => |code| {
714 if (code != 0) {
715 // TODO parse this output and surface with the Compilation API rather than
716 // directly outputting to stderr here.
717 std.debug.print("{s}", .{stderr});
718 return error.LLDReportedFailure;
719 }
720 },
721 else => {
722 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
723 return error.LLDCrashed;
724 },
725 }
693 if (comp.clang_passthrough_mode) {
694 child.stdin_behavior = .Inherit;
695 child.stdout_behavior = .Inherit;
696 child.stderr_behavior = .Inherit;
697
698 const term = child.spawnAndWait() catch |err| {
699 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
700 return error.UnableToSpawnSelf;
701 };
702 switch (term) {
703 .Exited => |code| {
704 if (code != 0) {
705 // TODO https://github.com/ziglang/zig/issues/6342
706 std.process.exit(1);
707 }
708 },
709 else => std.process.abort(),
710 }
711 } else {
712 child.stdin_behavior = .Ignore;
713 child.stdout_behavior = .Ignore;
714 child.stderr_behavior = .Pipe;
715
716 try child.spawn();
717
718 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
719
720 const term = child.wait() catch |err| {
721 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
722 return error.UnableToSpawnSelf;
723 };
724
725 switch (term) {
726 .Exited => |code| {
727 if (code != 0) {
728 // TODO parse this output and surface with the Compilation API rather than
729 // directly outputting to stderr here.
730 std.debug.print("{s}", .{stderr});
731 return error.LLDReportedFailure;
732 }
733 },
734 else => {
735 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
736 return error.LLDCrashed;
737 },
738 }
726739
727 if (stderr.len != 0) {
728 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
740 if (stderr.len != 0) {
741 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
742 }
729743 }
730744
731745 // At this stage, LLD has done its job. It is time to patch the resultant
src/link/Wasm.zig+46-32
......@@ -403,46 +403,60 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
403403 }
404404
405405 // Sadly, we must run LLD as a child process because it does not behave
406 // properly as a library. One exception is if we are running in passthrough
407 // mode, which means Clang / LLD should inherit stdio and are allowed to
408 // crash zig directly.
409 if (comp.clang_passthrough_mode) {
410 return @import("../main.zig").punt_to_lld(arena, argv.items);
411 }
412
406 // properly as a library.
413407 const child = try std.ChildProcess.init(argv.items, arena);
414408 defer child.deinit();
415409
416 child.stdin_behavior = .Ignore;
417 child.stdout_behavior = .Ignore;
418 child.stderr_behavior = .Pipe;
410 if (comp.clang_passthrough_mode) {
411 child.stdin_behavior = .Inherit;
412 child.stdout_behavior = .Inherit;
413 child.stderr_behavior = .Inherit;
419414
420 try child.spawn();
415 const term = child.spawnAndWait() catch |err| {
416 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
417 return error.UnableToSpawnSelf;
418 };
419 switch (term) {
420 .Exited => |code| {
421 if (code != 0) {
422 // TODO https://github.com/ziglang/zig/issues/6342
423 std.process.exit(1);
424 }
425 },
426 else => std.process.abort(),
427 }
428 } else {
429 child.stdin_behavior = .Ignore;
430 child.stdout_behavior = .Ignore;
431 child.stderr_behavior = .Pipe;
421432
422 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
433 try child.spawn();
423434
424 const term = child.wait() catch |err| {
425 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
426 return error.UnableToSpawnSelf;
427 };
435 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
428436
429 switch (term) {
430 .Exited => |code| {
431 if (code != 0) {
432 // TODO parse this output and surface with the Compilation API rather than
433 // directly outputting to stderr here.
434 std.debug.print("{s}", .{stderr});
435 return error.LLDReportedFailure;
436 }
437 },
438 else => {
439 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
440 return error.LLDCrashed;
441 },
442 }
437 const term = child.wait() catch |err| {
438 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
439 return error.UnableToSpawnSelf;
440 };
443441
444 if (stderr.len != 0) {
445 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
442 switch (term) {
443 .Exited => |code| {
444 if (code != 0) {
445 // TODO parse this output and surface with the Compilation API rather than
446 // directly outputting to stderr here.
447 std.debug.print("{s}", .{stderr});
448 return error.LLDReportedFailure;
449 }
450 },
451 else => {
452 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
453 return error.LLDCrashed;
454 },
455 }
456
457 if (stderr.len != 0) {
458 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
459 }
446460 }
447461
448462 if (!self.base.options.disable_lld_caching) {