From 958faa7031c7b50a544e151fea4d486e1c4926c1 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sun, 12 Oct 2025 13:54:00 -0400 Subject: [PATCH] windows: workaround kernel race condition the most --- src/link.zig | 9 ++++++--- test/standalone/windows_spawn/main.zig | 21 +++++++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/link.zig b/src/link.zig index 0a63ee0843..a0acce1073 100644 --- a/src/link.zig +++ b/src/link.zig @@ -616,19 +616,22 @@ pub const File = struct { &coff.mf else unreachable; - mf.file = for (0..10) |_| break base.emit.root_dir.handle.openFile(base.emit.sub_path, .{ + var attempt: u5 = 0; + mf.file = while (true) break base.emit.root_dir.handle.openFile(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(10); + std.os.windows.kernel32.Sleep(@as(u32, 1) << attempt >> 1); + attempt += 1; continue; }, else => return error.AccessDenied, }, else => |e| return e, - } else return error.AccessDenied; + }; base.file = mf.file; try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1])); }, diff --git a/test/standalone/windows_spawn/main.zig b/test/standalone/windows_spawn/main.zig index d8e259932e..b51e09451c 100644 --- a/test/standalone/windows_spawn/main.zig +++ b/test/standalone/windows_spawn/main.zig @@ -71,14 +71,19 @@ pub fn main() anyerror!void { try testExec(allocator, "heLLo", "hello from exe\n"); // now rename the exe to not have an extension - for (0..10) |_| break tmp.dir.rename("hello.exe", "hello") catch |err| switch (err) { - error.AccessDenied => { - // give the kernel a chance to finish closing the executable handle - std.os.windows.kernel32.Sleep(10); - continue; - }, - else => |e| return e, - } else return error.AccessDenied; + { + var attempt: u5 = 0; + while (true) break tmp.dir.rename("hello.exe", "hello") catch |err| switch (err) { + error.AccessDenied => { + 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 => |e| return e, + }; + } // with extension should now fail try testExecError(error.FileNotFound, allocator, "hello.exe");