zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

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:
Msrc/Compilation.zig | 2+-
Msrc/link/Coff.zig | 86++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/link/Elf.zig | 78++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/link/MachO.zig | 86++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/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) {