authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-17 16:54:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-18 16:52:43-07:00
logcb635e084b0c36e3c7a6bf63f49f7e7e9918532d
tree92d53f835566b630fd39f44a5e8c8ef9b3339add
parent9ee4530b9b38805f88a1e3df4b4b74db240f05df

stage2: better handling of CacheMode.whole on Windows

Windows gives AccessDenied if you delete a directory which contains open file handles. This could be triggered when using CacheMode.whole when cross compiling macho test binaries.

2 files changed, 20 insertions(+), 10 deletions(-)

src/Compilation.zig+14-2
......@@ -2390,9 +2390,21 @@ pub fn update(comp: *Compilation) !void {
23902390 const o_sub_path = try std.fs.path.join(comp.gpa, &[_][]const u8{ "o", &digest });
23912391 defer comp.gpa.free(o_sub_path);
23922392
2393 // Work around windows `AccessDenied` if any files within this directory are open
2394 // by doing the makeExecutable/makeWritable dance.
2395 const need_writable_dance = builtin.os.tag == .windows and comp.bin_file.file != null;
2396 if (need_writable_dance) {
2397 try comp.bin_file.makeExecutable();
2398 }
2399
23932400 try comp.bin_file.renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path);
23942401 comp.wholeCacheModeSetBinFilePath(&digest);
23952402
2403 // Has to be after the `wholeCacheModeSetBinFilePath` above.
2404 if (need_writable_dance) {
2405 try comp.bin_file.makeWritable();
2406 }
2407
23962408 // This is intentionally sandwiched between renameTmpIntoCache() and writeManifest().
23972409 if (comp.bin_file.options.module) |module| {
23982410 // We need to set the zig_cache_artifact_directory for -femit-asm, -femit-llvm-ir,
......@@ -3207,8 +3219,8 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
32073219 // TODO Surface more error details.
32083220 comp.lockAndSetMiscFailure(
32093221 .mingw_crt_file,
3210 "unable to build mingw-w64 CRT file: {s}",
3211 .{@errorName(err)},
3222 "unable to build mingw-w64 CRT file {s}: {s}",
3223 .{ @tagName(crt_file), @errorName(err) },
32123224 );
32133225 };
32143226 },
src/link.zig+6-8
......@@ -403,10 +403,8 @@ pub const File = struct {
403403 try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, emit.sub_path, .{});
404404 }
405405 }
406 if (base.intermediary_basename == null) {
407 f.close();
408 base.file = null;
409 }
406 f.close();
407 base.file = null;
410408 },
411409 .coff, .elf, .plan9, .wasm => if (base.file) |f| {
412410 if (base.intermediary_basename != null) {
......@@ -777,7 +775,7 @@ pub const File = struct {
777775 _ = base;
778776 while (true) {
779777 if (builtin.os.tag == .windows) {
780 // workaround windows `renameW` can't fail with `PathAlreadyExists`
778 // Work around windows `renameW` can't fail with `PathAlreadyExists`
781779 // See https://github.com/ziglang/zig/issues/8362
782780 if (cache_directory.handle.access(o_sub_path, .{})) |_| {
783781 try cache_directory.handle.deleteTree(o_sub_path);
......@@ -791,9 +789,9 @@ pub const File = struct {
791789 tmp_dir_sub_path,
792790 cache_directory.handle,
793791 o_sub_path,
794 ) catch |err| switch (err) {
795 error.AccessDenied => unreachable, // We are most likely trying to move a dir with open handles to its resources
796 else => |e| return e,
792 ) catch |err| {
793 log.err("unable to rename cache dir {s} to {s}: {s}", .{ tmp_dir_sub_path, o_sub_path, @errorName(err) });
794 return err;
797795 };
798796 break;
799797 } else {