| author | |
| committer | |
| log | b2bc6073c8ada065906da9e3b5a4a2e7db04c21d |
| tree | ddaba6a7a70c69ae72bad8c6c5644596e427040c |
| parent | c17e18647bf55bae38a1837a6afb19b0f2393892 |
This was causing flaky CI failures.3 files changed, 22 insertions(+), 3 deletions(-)
lib/std/os/windows.zig+2| ... | @@ -1912,6 +1912,7 @@ pub const CreateProcessError = error{ | ... | @@ -1912,6 +1912,7 @@ pub const CreateProcessError = error{ |
| 1912 | NameTooLong, | 1912 | NameTooLong, |
| 1913 | InvalidExe, | 1913 | InvalidExe, |
| 1914 | SystemResources, | 1914 | SystemResources, |
| 1915 | FileBusy, | ||
| 1915 | Unexpected, | 1916 | Unexpected, |
| 1916 | }; | 1917 | }; |
| 1917 | 1918 | ||
| ... | @@ -1982,6 +1983,7 @@ pub fn CreateProcessW( | ... | @@ -1982,6 +1983,7 @@ pub fn CreateProcessW( |
| 1982 | .INVALID_PARAMETER => unreachable, | 1983 | .INVALID_PARAMETER => unreachable, |
| 1983 | .INVALID_NAME => return error.InvalidName, | 1984 | .INVALID_NAME => return error.InvalidName, |
| 1984 | .FILENAME_EXCED_RANGE => return error.NameTooLong, | 1985 | .FILENAME_EXCED_RANGE => return error.NameTooLong, |
| 1986 | .SHARING_VIOLATION => return error.FileBusy, | ||
| 1985 | // These are all the system errors that are mapped to ENOEXEC by | 1987 | // These are all the system errors that are mapped to ENOEXEC by |
| 1986 | // the undocumented _dosmaperr (old CRT) or __acrt_errno_map_os_error | 1988 | // the undocumented _dosmaperr (old CRT) or __acrt_errno_map_os_error |
| 1987 | // (newer CRT) functions. Their code can be found in crt/src/dosmap.c (old SDK) | 1989 | // (newer CRT) functions. Their code can be found in crt/src/dosmap.c (old SDK) |
src/link.zig+12-2| ... | @@ -616,9 +616,19 @@ pub const File = struct { | ... | @@ -616,9 +616,19 @@ pub const File = struct { |
| 616 | &coff.mf | 616 | &coff.mf |
| 617 | else | 617 | else |
| 618 | unreachable; | 618 | unreachable; |
| 619 | mf.file = try base.emit.root_dir.handle.openFile(base.emit.sub_path, .{ | 619 | mf.file = for (0..2) |_| break base.emit.root_dir.handle.openFile(base.emit.sub_path, .{ |
| 620 | .mode = .read_write, | 620 | .mode = .read_write, |
| 621 | }); | 621 | }) catch |err| switch (err) { |
| 622 | error.AccessDenied => switch (builtin.os.tag) { | ||
| 623 | .windows => { | ||
| 624 | // give the kernel a chance to finish closing the executable handle | ||
| 625 | std.os.windows.kernel32.Sleep(0); | ||
| 626 | continue; | ||
| 627 | }, | ||
| 628 | else => return error.AccessDenied, | ||
| 629 | }, | ||
| 630 | else => |e| return e, | ||
| 631 | } else return error.AccessDenied; | ||
| 622 | base.file = mf.file; | 632 | base.file = mf.file; |
| 623 | try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1])); | 633 | try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1])); |
| 624 | }, | 634 | }, |
test/standalone/windows_spawn/main.zig+8-1| ... | @@ -71,7 +71,14 @@ pub fn main() anyerror!void { | ... | @@ -71,7 +71,14 @@ 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 | try tmp.dir.rename("hello.exe", "hello"); | 74 | for (0..2) |_| 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(0); | ||
| 78 | continue; | ||
| 79 | }, | ||
| 80 | else => |e| return e, | ||
| 81 | } else return error.AccessDenied; | ||
| 75 | 82 | ||
| 76 | // with extension should now fail | 83 | // with extension should now fail |
| 77 | try testExecError(error.FileNotFound, allocator, "hello.exe"); | 84 | try testExecError(error.FileNotFound, allocator, "hello.exe"); |