mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
link: move the windows kernel bug workaround to Io implementation
This commit is contained in:
parent
02119362d7
commit
df4c30ca16
2 changed files with 31 additions and 25 deletions
|
|
@ -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,
|
||||
|
|
|
|||
31
src/link.zig
31
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]));
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue