commit d3f7cf7345020410cbb0b3ff2e19947752283846 (tree)
parent b52a2ff73bb5796995c54f2ba7b9cf5f8ee38297
Author: Ryan Liptak <squeek502@hotmail.com>
Date: Tue, 23 Jun 2026 19:44:36 -0700
Io.Threaded: Fix dirReadLinkWindows not handling its async handle correctly
NtCreateFile is called with `.IO = .ASYNCHRONOUS` but then `NtFsControlFile` is called without any handling of `PENDING`. By switching to the `deviceIoControl` helper function, `PENDING` is handled since we are passing `.nonblocking = true`.
Fixes https://codeberg.org/ziglang/zig/issues/35871
Diffstat:
1 file changed, 10 insertions(+), 25 deletions(-)
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
@@ -8176,31 +8176,16 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink
defer windows.CloseHandle(result_handle);
var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(windows.REPARSE_DATA_BUFFER)) = undefined;
-
- syscall = try .start();
- while (true) switch (windows.ntdll.NtFsControlFile(
- result_handle,
- null, // event
- null, // APC routine
- null, // APC context
- &io_status_block,
- .GET_REPARSE_POINT,
- null, // input buffer
- 0, // input buffer length
- &reparse_buf,
- reparse_buf.len,
- )) {
- .SUCCESS => {
- syscall.finish();
- break;
- },
- .CANCELLED => {
- try syscall.checkCancel();
- continue;
- },
- .NOT_A_REPARSE_POINT => return syscall.fail(error.NotLink),
- else => |status| return syscall.unexpectedNtstatus(status),
- };
+ switch ((try deviceIoControl(&.{
+ .file = .{ .handle = result_handle, .flags = .{ .nonblocking = true } },
+ .code = .GET_REPARSE_POINT,
+ .out = &reparse_buf,
+ })).u.Status) {
+ .SUCCESS => {},
+ .CANCELLED => unreachable,
+ .NOT_A_REPARSE_POINT => return error.NotLink,
+ else => |status| return windows.unexpectedStatus(status),
+ }
const reparse_struct: *const windows.REPARSE_DATA_BUFFER = @ptrCast(@alignCast(&reparse_buf));
const IoReparseTagInt = @typeInfo(windows.IO_REPARSE_TAG).@"struct".backing_integer.?;