diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 0f0b043ce0..00f14ed741 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -2705,18 +2705,6 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa var delay_interval: windows.LARGE_INTEGER = timeoutToWindowsInterval(timeout); while (true) { - const alertable_syscall = try AlertableSyscall.start(); - const delay_rc = windows.ntdll.NtDelayExecution(windows.TRUE, &delay_interval); - alertable_syscall.finish(); - switch (delay_rc) { - .SUCCESS => { - // The thread woke due to the timeout. Although spurious - // timeouts are OK, when no deadline is passed we must not - // return `error.Timeout`. - if (timeout != .none) return error.Timeout; - }, - else => {}, - } var any_done = false; var any_pending = false; for (metadatas, 0..) |*metadata, op_usize| { @@ -2738,6 +2726,18 @@ fn batchWaitWindows(t: *Threaded, b: *Io.Batch, timeout: Io.Timeout) Io.Batch.Wa } if (any_done) return; if (!any_pending) return; + const alertable_syscall = try AlertableSyscall.start(); + const delay_rc = windows.ntdll.NtDelayExecution(windows.TRUE, &delay_interval); + alertable_syscall.finish(); + switch (delay_rc) { + .SUCCESS => { + // The thread woke due to the timeout. Although spurious + // timeouts are OK, when no deadline is passed we must not + // return `error.Timeout`. + if (timeout != .none) return error.Timeout; + }, + else => {}, + } } } @@ -8707,7 +8707,11 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us fn ntReadFileResult(io_status_block: *windows.IO_STATUS_BLOCK) !usize { switch (io_status_block.u.Status) { - .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => return io_status_block.Information, + .SUCCESS => { + assert(io_status_block.Information != 0); + return io_status_block.Information; + }, + .END_OF_FILE, .PIPE_BROKEN => return 0, .PENDING => unreachable, .INVALID_DEVICE_REQUEST => return error.IsDir, .LOCK_NOT_GRANTED => return error.LockViolation, @@ -8744,6 +8748,17 @@ fn ntReadFile(handle: windows.HANDLE, data: []const []u8, iosb: *windows.IO_STAT syscall.finish(); return .pending; }, + .SUCCESS => { + // Only END_OF_FILE is the true end. + if (iosb.Information == 0) { + try syscall.checkCancel(); + continue; + } else { + syscall.finish(); + iosb.u.Status = .SUCCESS; + return .status; + } + }, .CANCELLED => { try syscall.checkCancel(); continue; @@ -9709,6 +9724,7 @@ fn writeFileStreamingWindows( handle: windows.HANDLE, bytes: []const u8, ) File.Writer.Error!usize { + assert(bytes.len != 0); var bytes_written: windows.DWORD = undefined; const adjusted_len = std.math.lossyCast(u32, bytes.len); const syscall: Syscall = try .start(); diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index fe28e40cbb..b6785e4a33 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -188,9 +188,6 @@ pub extern "kernel32" fn PostQueuedCompletionStatus( lpOverlapped: ?*OVERLAPPED, ) callconv(.winapi) BOOL; -// TODO: -// GetOverlappedResultEx with bAlertable=false, which calls: GetStdHandle + WaitForSingleObjectEx. -// Uses the SwitchBack system to run implementations for older programs; Do we care about this? pub extern "kernel32" fn GetOverlappedResult( hFile: HANDLE, lpOverlapped: *OVERLAPPED,