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.
This commit is contained in:
@@ -2390,9 +2390,21 @@ pub fn update(comp: *Compilation) !void {
|
||||
const o_sub_path = try std.fs.path.join(comp.gpa, &[_][]const u8{ "o", &digest });
|
||||
defer comp.gpa.free(o_sub_path);
|
||||
|
||||
// Work around windows `AccessDenied` if any files within this directory are open
|
||||
// by doing the makeExecutable/makeWritable dance.
|
||||
const need_writable_dance = builtin.os.tag == .windows and comp.bin_file.file != null;
|
||||
if (need_writable_dance) {
|
||||
try comp.bin_file.makeExecutable();
|
||||
}
|
||||
|
||||
try comp.bin_file.renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path);
|
||||
comp.wholeCacheModeSetBinFilePath(&digest);
|
||||
|
||||
// Has to be after the `wholeCacheModeSetBinFilePath` above.
|
||||
if (need_writable_dance) {
|
||||
try comp.bin_file.makeWritable();
|
||||
}
|
||||
|
||||
// This is intentionally sandwiched between renameTmpIntoCache() and writeManifest().
|
||||
if (comp.bin_file.options.module) |module| {
|
||||
// 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 {
|
||||
// TODO Surface more error details.
|
||||
comp.lockAndSetMiscFailure(
|
||||
.mingw_crt_file,
|
||||
"unable to build mingw-w64 CRT file: {s}",
|
||||
.{@errorName(err)},
|
||||
"unable to build mingw-w64 CRT file {s}: {s}",
|
||||
.{ @tagName(crt_file), @errorName(err) },
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
14
src/link.zig
14
src/link.zig
@@ -403,10 +403,8 @@ pub const File = struct {
|
||||
try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, emit.sub_path, .{});
|
||||
}
|
||||
}
|
||||
if (base.intermediary_basename == null) {
|
||||
f.close();
|
||||
base.file = null;
|
||||
}
|
||||
f.close();
|
||||
base.file = null;
|
||||
},
|
||||
.coff, .elf, .plan9, .wasm => if (base.file) |f| {
|
||||
if (base.intermediary_basename != null) {
|
||||
@@ -777,7 +775,7 @@ pub const File = struct {
|
||||
_ = base;
|
||||
while (true) {
|
||||
if (builtin.os.tag == .windows) {
|
||||
// workaround windows `renameW` can't fail with `PathAlreadyExists`
|
||||
// Work around windows `renameW` can't fail with `PathAlreadyExists`
|
||||
// See https://github.com/ziglang/zig/issues/8362
|
||||
if (cache_directory.handle.access(o_sub_path, .{})) |_| {
|
||||
try cache_directory.handle.deleteTree(o_sub_path);
|
||||
@@ -791,9 +789,9 @@ pub const File = struct {
|
||||
tmp_dir_sub_path,
|
||||
cache_directory.handle,
|
||||
o_sub_path,
|
||||
) catch |err| switch (err) {
|
||||
error.AccessDenied => unreachable, // We are most likely trying to move a dir with open handles to its resources
|
||||
else => |e| return e,
|
||||
) catch |err| {
|
||||
log.err("unable to rename cache dir {s} to {s}: {s}", .{ tmp_dir_sub_path, o_sub_path, @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
break;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user