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: *...@@ -1804,7 +1804,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *
1804 if (comp.clang_preprocessor_mode == .stdout)1804 if (comp.clang_preprocessor_mode == .stdout)
1805 std.process.exit(0);1805 std.process.exit(0);
1806 },1806 },
1807 else => std.process.exit(1),1807 else => std.process.abort(),
1808 }1808 }
1809 } else {1809 } else {
1810 child.stdin_behavior = .Ignore;1810 child.stdin_behavior = .Ignore;
src/link/Coff.zig+50-36
...@@ -1153,46 +1153,60 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -1153,46 +1153,60 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
1153 }1153 }
11541154
1155 // Sadly, we must run LLD as a child process because it does not behave1155 // 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 passthrough1156 // properly as a library.
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
1163 const child = try std.ChildProcess.init(argv.items, arena);1157 const child = try std.ChildProcess.init(argv.items, arena);
1164 defer child.deinit();1158 defer child.deinit();
11651159
1166 child.stdin_behavior = .Ignore;1160 if (comp.clang_passthrough_mode) {
1167 child.stdout_behavior = .Ignore;1161 child.stdin_behavior = .Inherit;
1168 child.stderr_behavior = .Pipe;1162 child.stdout_behavior = .Inherit;
11691163 child.stderr_behavior = .Inherit;
1170 try child.spawn();1164
11711165 const term = child.spawnAndWait() catch |err| {
1172 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);1166 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
11731167 return error.UnableToSpawnSelf;
1174 const term = child.wait() catch |err| {1168 };
1175 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });1169 switch (term) {
1176 return error.UnableToSpawnSelf;1170 .Exited => |code| {
1177 };1171 if (code != 0) {
11781172 // TODO https://github.com/ziglang/zig/issues/6342
1179 switch (term) {1173 std.process.exit(1);
1180 .Exited => |code| {1174 }
1181 if (code != 0) {1175 },
1182 // TODO parse this output and surface with the Compilation API rather than1176 else => std.process.abort(),
1183 // directly outputting to stderr here.1177 }
1184 std.debug.print("{s}", .{stderr});1178 } else {
1185 return error.LLDReportedFailure;1179 child.stdin_behavior = .Ignore;
1186 }1180 child.stdout_behavior = .Ignore;
1187 },1181 child.stderr_behavior = .Pipe;
1188 else => {1182
1189 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });1183 try child.spawn();
1190 return error.LLDCrashed;1184
1191 },1185 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
1192 }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) {1207 if (stderr.len != 0) {
1195 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});1208 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
1209 }
1196 }1210 }
1197 }1211 }
11981212
src/link/Elf.zig+46-32
...@@ -1632,46 +1632,60 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1632,46 +1632,60 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1632 }1632 }
16331633
1634 // Sadly, we must run LLD as a child process because it does not behave1634 // 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 passthrough1635 // properly as a library.
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
1642 const child = try std.ChildProcess.init(argv.items, arena);1636 const child = try std.ChildProcess.init(argv.items, arena);
1643 defer child.deinit();1637 defer child.deinit();
16441638
1645 child.stdin_behavior = .Ignore;1639 if (comp.clang_passthrough_mode) {
1646 child.stdout_behavior = .Ignore;1640 child.stdin_behavior = .Inherit;
1647 child.stderr_behavior = .Pipe;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| {1664 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
1654 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1655 return error.UnableToSpawnSelf;
1656 };
16571665
1658 switch (term) {1666 const term = child.wait() catch |err| {
1659 .Exited => |code| {1667 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
1660 if (code != 0) {1668 return error.UnableToSpawnSelf;
1661 // TODO parse this output and surface with the Compilation API rather than1669 };
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 }
16721670
1673 if (stderr.len != 0) {1671 switch (term) {
1674 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});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 }
1675 }1689 }
16761690
1677 if (!self.base.options.disable_lld_caching) {1691 if (!self.base.options.disable_lld_caching) {
src/link/MachO.zig+50-36
...@@ -686,46 +686,60 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -686,46 +686,60 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
686 }686 }
687 } else {687 } else {
688 // Sadly, we must run LLD as a child process because it does not behave688 // 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 passthrough689 // properly as a library.
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
696 const child = try std.ChildProcess.init(argv.items, arena);690 const child = try std.ChildProcess.init(argv.items, arena);
697 defer child.deinit();691 defer child.deinit();
698692
699 child.stdin_behavior = .Ignore;693 if (comp.clang_passthrough_mode) {
700 child.stdout_behavior = .Ignore;694 child.stdin_behavior = .Inherit;
701 child.stderr_behavior = .Pipe;695 child.stdout_behavior = .Inherit;
702696 child.stderr_behavior = .Inherit;
703 try child.spawn();697
704698 const term = child.spawnAndWait() catch |err| {
705 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);699 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
706700 return error.UnableToSpawnSelf;
707 const term = child.wait() catch |err| {701 };
708 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });702 switch (term) {
709 return error.UnableToSpawnSelf;703 .Exited => |code| {
710 };704 if (code != 0) {
711705 // TODO https://github.com/ziglang/zig/issues/6342
712 switch (term) {706 std.process.exit(1);
713 .Exited => |code| {707 }
714 if (code != 0) {708 },
715 // TODO parse this output and surface with the Compilation API rather than709 else => std.process.abort(),
716 // directly outputting to stderr here.710 }
717 std.debug.print("{s}", .{stderr});711 } else {
718 return error.LLDReportedFailure;712 child.stdin_behavior = .Ignore;
719 }713 child.stdout_behavior = .Ignore;
720 },714 child.stderr_behavior = .Pipe;
721 else => {715
722 log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });716 try child.spawn();
723 return error.LLDCrashed;717
724 },718 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
725 }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) {740 if (stderr.len != 0) {
728 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});741 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
742 }
729 }743 }
730744
731 // At this stage, LLD has done its job. It is time to patch the resultant745 // 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 {...@@ -403,46 +403,60 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
403 }403 }
404404
405 // Sadly, we must run LLD as a child process because it does not behave405 // 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 passthrough406 // properly as a library.
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
413 const child = try std.ChildProcess.init(argv.items, arena);407 const child = try std.ChildProcess.init(argv.items, arena);
414 defer child.deinit();408 defer child.deinit();
415409
416 child.stdin_behavior = .Ignore;410 if (comp.clang_passthrough_mode) {
417 child.stdout_behavior = .Ignore;411 child.stdin_behavior = .Inherit;
418 child.stderr_behavior = .Pipe;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| {435 const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
425 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
426 return error.UnableToSpawnSelf;
427 };
428436
429 switch (term) {437 const term = child.wait() catch |err| {
430 .Exited => |code| {438 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
431 if (code != 0) {439 return error.UnableToSpawnSelf;
432 // TODO parse this output and surface with the Compilation API rather than440 };
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 }
443441
444 if (stderr.len != 0) {442 switch (term) {
445 std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});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 }
446 }460 }
447461
448 if (!self.base.options.disable_lld_caching) {462 if (!self.base.options.disable_lld_caching) {