Skip to content
This repository was archived by the owner on Mar 13, 2026. It is now read-only.

Commit d4df65e

Browse files
ianprime0509mlugg
authored andcommitted
std.Build.Step.Compile: fix race condition in args file creation
Fixes ziglang#23993 Previously, if multiple build processes tried to create the same args file, there was a race condition with the use of the non-atomic `writeFile` function which could cause a spawned compiler to read an empty or incomplete args file. This commit avoids the race condition by first writing to a temporary file with a random path and renaming it to the desired path.
1 parent d57b1e3 commit d4df65e

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

lib/std/Build/Step/Compile.zig

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,26 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
18271827
_ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash});
18281828

18291829
const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash;
1830-
try b.cache_root.handle.writeFile(.{ .sub_path = args_file, .data = args });
1830+
if (b.cache_root.handle.access(args_file, .{})) |_| {
1831+
// The args file is already present from a previous run.
1832+
} else |err| switch (err) {
1833+
error.FileNotFound => {
1834+
try b.cache_root.handle.makePath("tmp");
1835+
const rand_int = std.crypto.random.int(u64);
1836+
const tmp_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int);
1837+
try b.cache_root.handle.writeFile(.{ .sub_path = tmp_path, .data = args });
1838+
defer b.cache_root.handle.deleteFile(tmp_path) catch {
1839+
// It's fine if the temporary file can't be cleaned up.
1840+
};
1841+
b.cache_root.handle.rename(tmp_path, args_file) catch |rename_err| switch (rename_err) {
1842+
error.PathAlreadyExists => {
1843+
// The args file was created by another concurrent build process.
1844+
},
1845+
else => |other_err| return other_err,
1846+
};
1847+
},
1848+
else => |other_err| return other_err,
1849+
}
18311850

18321851
const resolved_args_file = try mem.concat(arena, u8, &.{
18331852
"@",

0 commit comments

Comments
 (0)