Commit df4c30ca16
Changed files (2)
lib
std
src
lib/std/Io/Threaded.zig
@@ -2081,6 +2081,10 @@ fn dirOpenFileWindowsInner(
const create_file_flags: w.ULONG = file_or_dir_flag |
if (flags.follow_symlinks) blocking_flag else w.FILE_OPEN_REPARSE_POINT;
+ // There are multiple kernel bugs being worked around with retries.
+ const max_attempts = 13;
+ var attempt: u5 = 0;
+
const handle = while (true) {
try t.checkCancel();
@@ -2110,7 +2114,17 @@ fn dirOpenFileWindowsInner(
.NO_MEDIA_IN_DEVICE => return error.NoDevice,
.INVALID_PARAMETER => |err| return w.statusBug(err),
.SHARING_VIOLATION => return error.AccessDenied,
- .ACCESS_DENIED => return error.AccessDenied,
+ .ACCESS_DENIED => {
+ // This occurs if the file attempting to be opened is a running
+ // executable. However, there's a kernel bug: the error may be
+ // incorrectly returned for an indeterminate amount of time
+ // after an executable file is closed. Here we work around the
+ // kernel bug with retry attempts.
+ if (attempt - max_attempts == 0) return error.AccessDenied;
+ _ = w.kernel32.SleepEx((@as(u32, 1) << attempt) >> 1, w.TRUE);
+ attempt += 1;
+ continue;
+ },
.PIPE_BUSY => return error.PipeBusy,
.PIPE_NOT_AVAILABLE => return error.NoDevice,
.OBJECT_PATH_SYNTAX_BAD => |err| return w.statusBug(err),
@@ -2123,10 +2137,11 @@ fn dirOpenFileWindowsInner(
// This error means that there *was* a file in this location on
// the file system, but it was deleted. However, the OS is not
// finished with the deletion operation, and so this CreateFile
- // call has failed. There is not really a sane way to handle
- // this other than retrying the creation after the OS finishes
- // the deletion.
- _ = w.kernel32.SleepEx(1, w.FALSE);
+ // call has failed. Here, we simulate the kernel bug being
+ // fixed by sleeping and retrying until the error goes away.
+ if (attempt - max_attempts == 0) return error.AccessDenied;
+ _ = w.kernel32.SleepEx((@as(u32, 1) << attempt) >> 1, w.TRUE);
+ attempt += 1;
continue;
},
.VIRUS_INFECTED, .VIRUS_DELETED => return error.AntivirusInterference,
src/link.zig
@@ -1,19 +1,22 @@
-const std = @import("std");
-const build_options = @import("build_options");
const builtin = @import("builtin");
+const build_options = @import("build_options");
+
+const std = @import("std");
+const Io = std.Io;
const assert = std.debug.assert;
const fs = std.fs;
const mem = std.mem;
const log = std.log.scoped(.link);
-const trace = @import("tracy.zig").trace;
-const wasi_libc = @import("libs/wasi_libc.zig");
-
const Allocator = std.mem.Allocator;
const Cache = std.Build.Cache;
const Path = std.Build.Cache.Path;
const Directory = std.Build.Cache.Directory;
const Compilation = @import("Compilation.zig");
const LibCInstallation = std.zig.LibCInstallation;
+
+const trace = @import("tracy.zig").trace;
+const wasi_libc = @import("libs/wasi_libc.zig");
+
const Zcu = @import("Zcu.zig");
const InternPool = @import("InternPool.zig");
const Type = @import("Type.zig");
@@ -572,6 +575,7 @@ pub const File = struct {
dev.check(.make_writable);
const comp = base.comp;
const gpa = comp.gpa;
+ const io = comp.io;
switch (base.tag) {
.lld => assert(base.file == null),
.elf, .macho, .wasm, .goff, .xcoff => {
@@ -616,22 +620,9 @@ pub const File = struct {
&coff.mf
else
unreachable;
- var attempt: u5 = 0;
- mf.file = while (true) break base.emit.root_dir.handle.openFile(base.emit.sub_path, .{
+ mf.file = .adaptFromNewApi(try Io.Dir.openFile(base.emit.root_dir.handle.adaptToNewApi(), io, base.emit.sub_path, .{
.mode = .read_write,
- }) catch |err| switch (err) {
- error.AccessDenied => switch (builtin.os.tag) {
- .windows => {
- if (attempt == 13) return error.AccessDenied;
- // give the kernel a chance to finish closing the executable handle
- std.os.windows.kernel32.Sleep(@as(u32, 1) << attempt >> 1);
- attempt += 1;
- continue;
- },
- else => return error.AccessDenied,
- },
- else => |e| return e,
- };
+ }));
base.file = mf.file;
try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1]));
},