aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-12-26 13:50:26 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-12-26 13:50:26 -0700
commit3f9588ca29c721f11eb9dae8f6de8ebd1155c7bf (patch)
treecef7fd69c3dc20dabdda4f90d3a7fc5b2c46d13f /src
parented39ff202baf5bb73e54f7ecc20df63d9c190dc9 (diff)
downloadzig-3f9588ca29c721f11eb9dae8f6de8ebd1155c7bf.tar.gz
zig-3f9588ca29c721f11eb9dae8f6de8ebd1155c7bf.zip
std: do not call malloc() between fork() and execv()
We were violating the POSIX standard which resulted in a deadlock on musl v1.1.24 on aarch64 alpine linux, uncovered with the new ThreadPool usage in the stage2 compiler. std.os execv functions that accept an Allocator parameter are removed because they are footguns. The POSIX standard does not allow calls to malloc() between fork() and execv() and since it is common to both (1) call execv() after fork() and (2) use std.heap.c_allocator, Programmers are encouraged to go through the `std.process` API instead, causing some dissonance when combined with `std.os` APIs. I also slapped a big warning message on all the relevant doc comments.
Diffstat (limited to 'src')
-rw-r--r--src/main.zig14
1 files changed, 5 insertions, 9 deletions
diff --git a/src/main.zig b/src/main.zig
index 99d0dcd5f9..c23cba98d8 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -116,15 +116,13 @@ pub fn main() anyerror!void {
return mainArgs(gpa, arena, args);
}
-const os_can_execve = std.builtin.os.tag != .windows;
-
pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !void {
if (args.len <= 1) {
std.log.info("{}", .{usage});
fatal("expected command argument", .{});
}
- if (os_can_execve and std.os.getenvZ("ZIG_IS_DETECTING_LIBC_PATHS") != null) {
+ if (std.process.can_execv and std.os.getenvZ("ZIG_IS_DETECTING_LIBC_PATHS") != null) {
// In this case we have accidentally invoked ourselves as "the system C compiler"
// to figure out where libc is installed. This is essentially infinite recursion
// via child process execution due to the CC environment variable pointing to Zig.
@@ -147,11 +145,11 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
// CC environment variable. We detect and support this scenario here because of
// the ZIG_IS_DETECTING_LIBC_PATHS environment variable.
if (mem.eql(u8, args[1], "cc")) {
- return std.os.execvpe(arena, args[1..], &env_map);
+ return std.process.execve(arena, args[1..], &env_map);
} else {
const modified_args = try arena.dupe([]const u8, args);
modified_args[0] = "cc";
- return std.os.execvpe(arena, modified_args, &env_map);
+ return std.process.execve(arena, modified_args, &env_map);
}
}
@@ -1841,10 +1839,8 @@ fn buildOutputType(
}
// We do not execve for tests because if the test fails we want to print the error message and
// invocation below.
- if (os_can_execve and arg_mode == .run and !watch) {
- // TODO improve the std lib so that we don't need a call to getEnvMap here.
- var env_vars = try process.getEnvMap(arena);
- const err = std.os.execvpe(gpa, argv.items, &env_vars);
+ if (std.process.can_execv and arg_mode == .run and !watch) {
+ const err = std.process.execv(gpa, argv.items);
const cmd = try argvCmd(arena, argv.items);
fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd });
} else {