| ... | ... | @@ -1314,6 +1314,13 @@ const AlertableSyscall = struct { |
| 1314 | 1314 | } |
| 1315 | 1315 | }; |
| 1316 | 1316 | |
| 1317 | fn noopApc(_: ?*anyopaque, _: *windows.IO_STATUS_BLOCK, _: windows.ULONG) callconv(.winapi) void {} |
| 1318 | |
| 1319 | fn waitForApcOrAlert() void { |
| 1320 | const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER); |
| 1321 | _ = windows.ntdll.NtDelayExecution(windows.TRUE, &infinite_timeout); |
| 1322 | } |
| 1323 | |
| 1317 | 1324 | const max_iovecs_len = 8; |
| 1318 | 1325 | const splat_buffer_size = 64; |
| 1319 | 1326 | const default_PATH = "/usr/local/bin:/bin/:/usr/bin"; |
| ... | ... | @@ -8371,40 +8378,41 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8371 | 8378 | const buffer = data[index]; |
| 8372 | 8379 | |
| 8373 | 8380 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; |
| 8374 | | var done: bool = false; |
| 8375 | | const max_delay_interval: windows.LARGE_INTEGER = std.math.minInt(i64); |
| 8376 | | |
| 8377 | | read: { |
| 8378 | | const syscall: Syscall = try .start(); |
| 8379 | | while (true) { |
| 8380 | | switch (windows.ntdll.NtReadFile( |
| 8381 | | file.handle, |
| 8382 | | null, // event |
| 8383 | | flagApc, // apc callback |
| 8384 | | &done, // apc context |
| 8385 | | &io_status_block, |
| 8386 | | buffer.ptr, |
| 8387 | | @min(std.math.maxInt(u32), buffer.len), |
| 8388 | | null, // byte offset |
| 8389 | | null, // key |
| 8390 | | )) { |
| 8391 | | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => break :read syscall.finish(), |
| 8392 | | .PENDING => break, |
| 8393 | | .CANCELLED => { |
| 8394 | | try syscall.checkCancel(); |
| 8395 | | continue; |
| 8396 | | }, |
| 8397 | | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), |
| 8398 | | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), |
| 8399 | | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| 8400 | | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), // streaming read of async mode file |
| 8401 | | else => |status| return syscall.unexpectedNtstatus(status), |
| 8402 | | } |
| 8381 | const syscall: Syscall = try .start(); |
| 8382 | while (true) { |
| 8383 | io_status_block.u.Status = .PENDING; |
| 8384 | switch (windows.ntdll.NtReadFile( |
| 8385 | file.handle, |
| 8386 | null, // event |
| 8387 | noopApc, // apc callback |
| 8388 | null, // apc context |
| 8389 | &io_status_block, |
| 8390 | buffer.ptr, |
| 8391 | @min(std.math.maxInt(u32), buffer.len), |
| 8392 | null, // byte offset |
| 8393 | null, // key |
| 8394 | )) { |
| 8395 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => { |
| 8396 | syscall.finish(); |
| 8397 | return io_status_block.Information; |
| 8398 | }, |
| 8399 | .PENDING => break, |
| 8400 | .CANCELLED => { |
| 8401 | try syscall.checkCancel(); |
| 8402 | continue; |
| 8403 | }, |
| 8404 | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), |
| 8405 | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), |
| 8406 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| 8407 | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), // streaming read of async mode file |
| 8408 | else => |status| return syscall.unexpectedNtstatus(status), |
| 8403 | 8409 | } |
| 8410 | } |
| 8411 | { |
| 8404 | 8412 | // Once we get here we received PENDING so we must not return from the |
| 8405 | 8413 | // function until the operation completes. |
| 8406 | | defer while (!done) { |
| 8407 | | _ = windows.ntdll.NtDelayExecution(1, &max_delay_interval); |
| 8414 | defer while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8415 | waitForApcOrAlert(); |
| 8408 | 8416 | }; |
| 8409 | 8417 | |
| 8410 | 8418 | const alertable_syscall = syscall.toAlertable() catch |err| switch (err) { |
| ... | ... | @@ -8414,36 +8422,25 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8414 | 8422 | }, |
| 8415 | 8423 | }; |
| 8416 | 8424 | defer alertable_syscall.finish(); |
| 8417 | | while (!done) { |
| 8418 | | _ = windows.ntdll.NtDelayExecution(1, &max_delay_interval); |
| 8425 | waitForApcOrAlert(); |
| 8426 | while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8419 | 8427 | alertable_syscall.checkCancel() catch |err| switch (err) { |
| 8420 | 8428 | error.Canceled => |e| { |
| 8421 | 8429 | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); |
| 8422 | 8430 | return e; |
| 8423 | 8431 | }, |
| 8424 | 8432 | }; |
| 8433 | waitForApcOrAlert(); |
| 8425 | 8434 | } |
| 8426 | 8435 | } |
| 8427 | | |
| 8428 | 8436 | switch (io_status_block.u.Status) { |
| 8429 | | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => {}, |
| 8437 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => return io_status_block.Information, |
| 8438 | .PENDING => unreachable, // cannot return until the operation completes |
| 8430 | 8439 | .INVALID_DEVICE_REQUEST => return error.IsDir, |
| 8431 | 8440 | .LOCK_NOT_GRANTED => return error.LockViolation, |
| 8432 | 8441 | .ACCESS_DENIED => return error.AccessDenied, |
| 8433 | 8442 | else => |status| return windows.unexpectedStatus(status), |
| 8434 | 8443 | } |
| 8435 | | return io_status_block.Information; |
| 8436 | | } |
| 8437 | | |
| 8438 | | fn flagApc( |
| 8439 | | apc_context: ?*anyopaque, |
| 8440 | | io_status_block: *windows.IO_STATUS_BLOCK, |
| 8441 | | unused: windows.ULONG, |
| 8442 | | ) callconv(.winapi) void { |
| 8443 | | const flag: *bool = @ptrCast(apc_context); |
| 8444 | | flag.* = true; |
| 8445 | | _ = io_status_block; |
| 8446 | | _ = unused; |
| 8447 | 8444 | } |
| 8448 | 8445 | |
| 8449 | 8446 | fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { |
| ... | ... | @@ -14646,7 +14643,7 @@ fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE { |
| 14646 | 14643 | t.mutex.lock(); // Another thread might have won the race. |
| 14647 | 14644 | defer t.mutex.unlock(); |
| 14648 | 14645 | if (t.random_file.handle) |prev_handle| { |
| 14649 | | _ = windows.ntdll.NtClose(fresh_handle); |
| 14646 | windows.CloseHandle(fresh_handle); |
| 14650 | 14647 | return prev_handle; |
| 14651 | 14648 | } else { |
| 14652 | 14649 | t.random_file.handle = fresh_handle; |