commit 7dd4afb224f4ca747b8eb462c28337ce9a63d38c (tree)
parent 4592fd26b937d8c7ff91295408d8377c1c13cf53
Author: Andrew Kelley <andrew@ziglang.org>
Date: Tue, 8 Dec 2020 22:37:01 -0700
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.
Diffstat:
| M | src/Compilation.zig | | | 2 | +- |
| M | src/link/Coff.zig | | | 86 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
| M | src/link/Elf.zig | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
| M | src/link/MachO.zig | | | 86 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
| M | src/link/Wasm.zig | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
5 files changed, 193 insertions(+), 137 deletions(-)
diff --git a/src/Compilation.zig b/src/Compilation.zig
@@ -1804,7 +1804,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *
if (comp.clang_preprocessor_mode == .stdout)
std.process.exit(0);
},
- else => std.process.exit(1),
+ else => std.process.abort(),
}
} else {
child.stdin_behavior = .Ignore;
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
@@ -1153,46 +1153,60 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
}
// Sadly, we must run LLD as a child process because it does not behave
- // properly as a library. One exception is if we are running in passthrough
- // mode, which means Clang / LLD should inherit stdio and are allowed to
- // crash zig directly.
- if (comp.clang_passthrough_mode) {
- return @import("../main.zig").punt_to_lld(arena, argv.items);
- }
-
+ // properly as a library.
const child = try std.ChildProcess.init(argv.items, arena);
defer child.deinit();
- child.stdin_behavior = .Ignore;
- child.stdout_behavior = .Ignore;
- child.stderr_behavior = .Pipe;
-
- try child.spawn();
-
- const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
-
- const term = child.wait() catch |err| {
- log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
- return error.UnableToSpawnSelf;
- };
-
- switch (term) {
- .Exited => |code| {
- if (code != 0) {
- // TODO parse this output and surface with the Compilation API rather than
- // directly outputting to stderr here.
- std.debug.print("{s}", .{stderr});
- return error.LLDReportedFailure;
- }
- },
- else => {
- log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
- return error.LLDCrashed;
- },
- }
+ if (comp.clang_passthrough_mode) {
+ child.stdin_behavior = .Inherit;
+ child.stdout_behavior = .Inherit;
+ child.stderr_behavior = .Inherit;
+
+ const term = child.spawnAndWait() catch |err| {
+ log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
+ switch (term) {
+ .Exited => |code| {
+ if (code != 0) {
+ // TODO https://github.com/ziglang/zig/issues/6342
+ std.process.exit(1);
+ }
+ },
+ else => std.process.abort(),
+ }
+ } else {
+ child.stdin_behavior = .Ignore;
+ child.stdout_behavior = .Ignore;
+ child.stderr_behavior = .Pipe;
+
+ try child.spawn();
+
+ const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
+
+ const term = child.wait() catch |err| {
+ log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
+
+ switch (term) {
+ .Exited => |code| {
+ if (code != 0) {
+ // TODO parse this output and surface with the Compilation API rather than
+ // directly outputting to stderr here.
+ std.debug.print("{s}", .{stderr});
+ return error.LLDReportedFailure;
+ }
+ },
+ else => {
+ log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
+ return error.LLDCrashed;
+ },
+ }
- if (stderr.len != 0) {
- std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+ if (stderr.len != 0) {
+ std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+ }
}
}
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
@@ -1632,46 +1632,60 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
}
// Sadly, we must run LLD as a child process because it does not behave
- // properly as a library. One exception is if we are running in passthrough
- // mode, which means Clang / LLD should inherit stdio and are allowed to
- // crash zig directly.
- if (comp.clang_passthrough_mode) {
- return @import("../main.zig").punt_to_lld(arena, argv.items);
- }
-
+ // properly as a library.
const child = try std.ChildProcess.init(argv.items, arena);
defer child.deinit();
- child.stdin_behavior = .Ignore;
- child.stdout_behavior = .Ignore;
- child.stderr_behavior = .Pipe;
+ if (comp.clang_passthrough_mode) {
+ child.stdin_behavior = .Inherit;
+ child.stdout_behavior = .Inherit;
+ child.stderr_behavior = .Inherit;
- try child.spawn();
+ const term = child.spawnAndWait() catch |err| {
+ log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
+ switch (term) {
+ .Exited => |code| {
+ if (code != 0) {
+ // TODO https://github.com/ziglang/zig/issues/6342
+ std.process.exit(1);
+ }
+ },
+ else => std.process.abort(),
+ }
+ } else {
+ child.stdin_behavior = .Ignore;
+ child.stdout_behavior = .Ignore;
+ child.stderr_behavior = .Pipe;
- const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
+ try child.spawn();
- const term = child.wait() catch |err| {
- log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
- return error.UnableToSpawnSelf;
- };
+ const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
- switch (term) {
- .Exited => |code| {
- if (code != 0) {
- // TODO parse this output and surface with the Compilation API rather than
- // directly outputting to stderr here.
- std.debug.print("{s}", .{stderr});
- return error.LLDReportedFailure;
- }
- },
- else => {
- log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
- return error.LLDCrashed;
- },
- }
+ const term = child.wait() catch |err| {
+ log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
- if (stderr.len != 0) {
- std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+ switch (term) {
+ .Exited => |code| {
+ if (code != 0) {
+ // TODO parse this output and surface with the Compilation API rather than
+ // directly outputting to stderr here.
+ std.debug.print("{s}", .{stderr});
+ return error.LLDReportedFailure;
+ }
+ },
+ else => {
+ log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
+ return error.LLDCrashed;
+ },
+ }
+
+ if (stderr.len != 0) {
+ std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+ }
}
if (!self.base.options.disable_lld_caching) {
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
@@ -686,46 +686,60 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
}
} else {
// Sadly, we must run LLD as a child process because it does not behave
- // properly as a library. One exception is if we are running in passthrough
- // mode, which means Clang / LLD should inherit stdio and are allowed to
- // crash zig directly.
- if (comp.clang_passthrough_mode) {
- return @import("../main.zig").punt_to_lld(arena, argv.items);
- }
-
+ // properly as a library.
const child = try std.ChildProcess.init(argv.items, arena);
defer child.deinit();
- child.stdin_behavior = .Ignore;
- child.stdout_behavior = .Ignore;
- child.stderr_behavior = .Pipe;
-
- try child.spawn();
-
- const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
-
- const term = child.wait() catch |err| {
- log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
- return error.UnableToSpawnSelf;
- };
-
- switch (term) {
- .Exited => |code| {
- if (code != 0) {
- // TODO parse this output and surface with the Compilation API rather than
- // directly outputting to stderr here.
- std.debug.print("{s}", .{stderr});
- return error.LLDReportedFailure;
- }
- },
- else => {
- log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
- return error.LLDCrashed;
- },
- }
+ if (comp.clang_passthrough_mode) {
+ child.stdin_behavior = .Inherit;
+ child.stdout_behavior = .Inherit;
+ child.stderr_behavior = .Inherit;
+
+ const term = child.spawnAndWait() catch |err| {
+ log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
+ switch (term) {
+ .Exited => |code| {
+ if (code != 0) {
+ // TODO https://github.com/ziglang/zig/issues/6342
+ std.process.exit(1);
+ }
+ },
+ else => std.process.abort(),
+ }
+ } else {
+ child.stdin_behavior = .Ignore;
+ child.stdout_behavior = .Ignore;
+ child.stderr_behavior = .Pipe;
+
+ try child.spawn();
+
+ const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
+
+ const term = child.wait() catch |err| {
+ log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
+
+ switch (term) {
+ .Exited => |code| {
+ if (code != 0) {
+ // TODO parse this output and surface with the Compilation API rather than
+ // directly outputting to stderr here.
+ std.debug.print("{s}", .{stderr});
+ return error.LLDReportedFailure;
+ }
+ },
+ else => {
+ log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
+ return error.LLDCrashed;
+ },
+ }
- if (stderr.len != 0) {
- std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+ if (stderr.len != 0) {
+ std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+ }
}
// At this stage, LLD has done its job. It is time to patch the resultant
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
@@ -403,46 +403,60 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
}
// Sadly, we must run LLD as a child process because it does not behave
- // properly as a library. One exception is if we are running in passthrough
- // mode, which means Clang / LLD should inherit stdio and are allowed to
- // crash zig directly.
- if (comp.clang_passthrough_mode) {
- return @import("../main.zig").punt_to_lld(arena, argv.items);
- }
-
+ // properly as a library.
const child = try std.ChildProcess.init(argv.items, arena);
defer child.deinit();
- child.stdin_behavior = .Ignore;
- child.stdout_behavior = .Ignore;
- child.stderr_behavior = .Pipe;
+ if (comp.clang_passthrough_mode) {
+ child.stdin_behavior = .Inherit;
+ child.stdout_behavior = .Inherit;
+ child.stderr_behavior = .Inherit;
- try child.spawn();
+ const term = child.spawnAndWait() catch |err| {
+ log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
+ switch (term) {
+ .Exited => |code| {
+ if (code != 0) {
+ // TODO https://github.com/ziglang/zig/issues/6342
+ std.process.exit(1);
+ }
+ },
+ else => std.process.abort(),
+ }
+ } else {
+ child.stdin_behavior = .Ignore;
+ child.stdout_behavior = .Ignore;
+ child.stderr_behavior = .Pipe;
- const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
+ try child.spawn();
- const term = child.wait() catch |err| {
- log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
- return error.UnableToSpawnSelf;
- };
+ const stderr = try child.stderr.?.reader().readAllAlloc(arena, 10 * 1024 * 1024);
- switch (term) {
- .Exited => |code| {
- if (code != 0) {
- // TODO parse this output and surface with the Compilation API rather than
- // directly outputting to stderr here.
- std.debug.print("{s}", .{stderr});
- return error.LLDReportedFailure;
- }
- },
- else => {
- log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
- return error.LLDCrashed;
- },
- }
+ const term = child.wait() catch |err| {
+ log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
+ return error.UnableToSpawnSelf;
+ };
- if (stderr.len != 0) {
- std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+ switch (term) {
+ .Exited => |code| {
+ if (code != 0) {
+ // TODO parse this output and surface with the Compilation API rather than
+ // directly outputting to stderr here.
+ std.debug.print("{s}", .{stderr});
+ return error.LLDReportedFailure;
+ }
+ },
+ else => {
+ log.err("{s} terminated with stderr:\n{s}", .{ argv.items[0], stderr });
+ return error.LLDCrashed;
+ },
+ }
+
+ if (stderr.len != 0) {
+ std.log.warn("unexpected LLD stderr:\n{s}", .{stderr});
+ }
}
if (!self.base.options.disable_lld_caching) {