| author | |
| committer | |
| log | 958faa7031c7b50a544e151fea4d486e1c4926c1 |
| tree | eeb3f0238b95ec4c6fd1647798ae877b4701873c |
| parent | ea694bfdb762a4dd18654c73aaaaf1b917d99cc3 |
2 files changed, 19 insertions(+), 11 deletions(-)
src/link.zig+6-3| ... | @@ -616,19 +616,22 @@ pub const File = struct { | ... | @@ -616,19 +616,22 @@ pub const File = struct { |
| 616 | &coff.mf | 616 | &coff.mf |
| 617 | else | 617 | else |
| 618 | unreachable; | 618 | 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, .{ | ||
| 620 | .mode = .read_write, | 621 | .mode = .read_write, |
| 621 | }) catch |err| switch (err) { | 622 | }) catch |err| switch (err) { |
| 622 | error.AccessDenied => switch (builtin.os.tag) { | 623 | error.AccessDenied => switch (builtin.os.tag) { |
| 623 | .windows => { | 624 | .windows => { |
| 625 | if (attempt == 13) return error.AccessDenied; | ||
| 624 | // give the kernel a chance to finish closing the executable handle | 626 | // 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; | ||
| 626 | continue; | 629 | continue; |
| 627 | }, | 630 | }, |
| 628 | else => return error.AccessDenied, | 631 | else => return error.AccessDenied, |
| 629 | }, | 632 | }, |
| 630 | else => |e| return e, | 633 | else => |e| return e, |
| 631 | } else return error.AccessDenied; | 634 | }; |
| 632 | base.file = mf.file; | 635 | base.file = mf.file; |
| 633 | try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1])); | 636 | try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1])); |
| 634 | }, | 637 | }, |
test/standalone/windows_spawn/main.zig+13-8| ... | @@ -71,14 +71,19 @@ pub fn main() anyerror!void { | ... | @@ -71,14 +71,19 @@ pub fn main() anyerror!void { |
| 71 | try testExec(allocator, "heLLo", "hello from exe\n"); | 71 | try testExec(allocator, "heLLo", "hello from exe\n"); |
| 72 | 72 | ||
| 73 | // now rename the exe to not have an extension | 73 | // now rename the exe to not have an extension |
| 74 | for (0..10) |_| break tmp.dir.rename("hello.exe", "hello") catch |err| switch (err) { | 74 | { |
| 75 | error.AccessDenied => { | 75 | var attempt: u5 = 0; |
| 76 | // give the kernel a chance to finish closing the executable handle | 76 | while (true) break tmp.dir.rename("hello.exe", "hello") catch |err| switch (err) { |
| 77 | std.os.windows.kernel32.Sleep(10); | 77 | error.AccessDenied => { |
| 78 | continue; | 78 | if (attempt == 13) return error.AccessDenied; |
| 79 | }, | 79 | // give the kernel a chance to finish closing the executable handle |
| 80 | else => |e| return e, | 80 | std.os.windows.kernel32.Sleep(@as(u32, 1) << attempt >> 1); |
| 81 | } else return error.AccessDenied; | 81 | attempt += 1; |
| 82 | continue; | ||
| 83 | }, | ||
| 84 | else => |e| return e, | ||
| 85 | }; | ||
| 86 | } | ||
| 82 | 87 | ||
| 83 | // with extension should now fail | 88 | // with extension should now fail |
| 84 | try testExecError(error.FileNotFound, allocator, "hello.exe"); | 89 | try testExecError(error.FileNotFound, allocator, "hello.exe"); |