authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-10-12 13:54:00-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-10-12 13:55:57-04:00
log958faa7031c7b50a544e151fea4d486e1c4926c1
treeeeb3f0238b95ec4c6fd1647798ae877b4701873c
parentea694bfdb762a4dd18654c73aaaaf1b917d99cc3

windows: workaround kernel race condition the most


2 files changed, 19 insertions(+), 11 deletions(-)

src/link.zig+6-3
......@@ -616,19 +616,22 @@ pub const File = struct {
616616 &coff.mf
617617 else
618618 unreachable;
619 mf.file = for (0..10) |_| break base.emit.root_dir.handle.openFile(base.emit.sub_path, .{
619 var attempt: u5 = 0;
620 mf.file = while (true) break base.emit.root_dir.handle.openFile(base.emit.sub_path, .{
620621 .mode = .read_write,
621622 }) catch |err| switch (err) {
622623 error.AccessDenied => switch (builtin.os.tag) {
623624 .windows => {
625 if (attempt == 13) return error.AccessDenied;
624626 // give the kernel a chance to finish closing the executable handle
625 std.os.windows.kernel32.Sleep(10);
627 std.os.windows.kernel32.Sleep(@as(u32, 1) << attempt >> 1);
628 attempt += 1;
626629 continue;
627630 },
628631 else => return error.AccessDenied,
629632 },
630633 else => |e| return e,
631 } else return error.AccessDenied;
634 };
632635 base.file = mf.file;
633636 try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1]));
634637 },
test/standalone/windows_spawn/main.zig+13-8
......@@ -71,14 +71,19 @@ pub fn main() anyerror!void {
7171 try testExec(allocator, "heLLo", "hello from exe\n");
7272
7373 // now rename the exe to not have an extension
74 for (0..10) |_| break tmp.dir.rename("hello.exe", "hello") catch |err| switch (err) {
75 error.AccessDenied => {
76 // give the kernel a chance to finish closing the executable handle
77 std.os.windows.kernel32.Sleep(10);
78 continue;
79 },
80 else => |e| return e,
81 } else return error.AccessDenied;
74 {
75 var attempt: u5 = 0;
76 while (true) break tmp.dir.rename("hello.exe", "hello") catch |err| switch (err) {
77 error.AccessDenied => {
78 if (attempt == 13) return error.AccessDenied;
79 // give the kernel a chance to finish closing the executable handle
80 std.os.windows.kernel32.Sleep(@as(u32, 1) << attempt >> 1);
81 attempt += 1;
82 continue;
83 },
84 else => |e| return e,
85 };
86 }
8287
8388 // with extension should now fail
8489 try testExecError(error.FileNotFound, allocator, "hello.exe");