| ... | ... | @@ -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"; |
| ... | ... | @@ -8228,40 +8235,41 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8228 | 8235 | const buffer = data[index]; |
| 8229 | 8236 | |
| 8230 | 8237 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; |
| 8231 | | var done: bool = false; |
| 8232 | | const max_delay_interval: windows.LARGE_INTEGER = std.math.minInt(i64); |
| 8233 | | |
| 8234 | | read: { |
| 8235 | | const syscall: Syscall = try .start(); |
| 8236 | | while (true) { |
| 8237 | | switch (windows.ntdll.NtReadFile( |
| 8238 | | file.handle, |
| 8239 | | null, // event |
| 8240 | | flagApc, // apc callback |
| 8241 | | &done, // apc context |
| 8242 | | &io_status_block, |
| 8243 | | buffer.ptr, |
| 8244 | | @min(std.math.maxInt(u32), buffer.len), |
| 8245 | | null, // byte offset |
| 8246 | | null, // key |
| 8247 | | )) { |
| 8248 | | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => break :read syscall.finish(), |
| 8249 | | .PENDING => break, |
| 8250 | | .CANCELLED => { |
| 8251 | | try syscall.checkCancel(); |
| 8252 | | continue; |
| 8253 | | }, |
| 8254 | | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), |
| 8255 | | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), |
| 8256 | | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| 8257 | | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), // streaming read of async mode file |
| 8258 | | else => |status| return syscall.unexpectedNtstatus(status), |
| 8259 | | } |
| 8238 | const syscall: Syscall = try .start(); |
| 8239 | while (true) { |
| 8240 | io_status_block.u.Status = .PENDING; |
| 8241 | switch (windows.ntdll.NtReadFile( |
| 8242 | file.handle, |
| 8243 | null, // event |
| 8244 | noopApc, // apc callback |
| 8245 | null, // apc context |
| 8246 | &io_status_block, |
| 8247 | buffer.ptr, |
| 8248 | @min(std.math.maxInt(u32), buffer.len), |
| 8249 | null, // byte offset |
| 8250 | null, // key |
| 8251 | )) { |
| 8252 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => { |
| 8253 | syscall.finish(); |
| 8254 | return io_status_block.Information; |
| 8255 | }, |
| 8256 | .PENDING => break, |
| 8257 | .CANCELLED => { |
| 8258 | try syscall.checkCancel(); |
| 8259 | continue; |
| 8260 | }, |
| 8261 | .INVALID_DEVICE_REQUEST => return syscall.fail(error.IsDir), |
| 8262 | .LOCK_NOT_GRANTED => return syscall.fail(error.LockViolation), |
| 8263 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| 8264 | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), // streaming read of async mode file |
| 8265 | else => |status| return syscall.unexpectedNtstatus(status), |
| 8260 | 8266 | } |
| 8267 | } |
| 8268 | { |
| 8261 | 8269 | // Once we get here we received PENDING so we must not return from the |
| 8262 | 8270 | // function until the operation completes. |
| 8263 | | defer while (!done) { |
| 8264 | | _ = windows.ntdll.NtDelayExecution(1, &max_delay_interval); |
| 8271 | defer while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8272 | waitForApcOrAlert(); |
| 8265 | 8273 | }; |
| 8266 | 8274 | |
| 8267 | 8275 | const alertable_syscall = syscall.toAlertable() catch |err| switch (err) { |
| ... | ... | @@ -8271,36 +8279,25 @@ fn fileReadStreamingWindows(file: File, data: []const []u8) File.Reader.Error!us |
| 8271 | 8279 | }, |
| 8272 | 8280 | }; |
| 8273 | 8281 | defer alertable_syscall.finish(); |
| 8274 | | while (!done) { |
| 8275 | | _ = windows.ntdll.NtDelayExecution(1, &max_delay_interval); |
| 8282 | waitForApcOrAlert(); |
| 8283 | while (@atomicLoad(windows.NTSTATUS, &io_status_block.u.Status, .acquire) == .PENDING) { |
| 8276 | 8284 | alertable_syscall.checkCancel() catch |err| switch (err) { |
| 8277 | 8285 | error.Canceled => |e| { |
| 8278 | 8286 | _ = windows.ntdll.NtCancelIoFile(file.handle, &io_status_block); |
| 8279 | 8287 | return e; |
| 8280 | 8288 | }, |
| 8281 | 8289 | }; |
| 8290 | waitForApcOrAlert(); |
| 8282 | 8291 | } |
| 8283 | 8292 | } |
| 8284 | | |
| 8285 | 8293 | switch (io_status_block.u.Status) { |
| 8286 | | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => {}, |
| 8294 | .SUCCESS, .END_OF_FILE, .PIPE_BROKEN => return io_status_block.Information, |
| 8295 | .PENDING => unreachable, // cannot return until the operation completes |
| 8287 | 8296 | .INVALID_DEVICE_REQUEST => return error.IsDir, |
| 8288 | 8297 | .LOCK_NOT_GRANTED => return error.LockViolation, |
| 8289 | 8298 | .ACCESS_DENIED => return error.AccessDenied, |
| 8290 | 8299 | else => |status| return windows.unexpectedStatus(status), |
| 8291 | 8300 | } |
| 8292 | | return io_status_block.Information; |
| 8293 | | } |
| 8294 | | |
| 8295 | | fn flagApc( |
| 8296 | | apc_context: ?*anyopaque, |
| 8297 | | io_status_block: *windows.IO_STATUS_BLOCK, |
| 8298 | | unused: windows.ULONG, |
| 8299 | | ) callconv(.winapi) void { |
| 8300 | | const flag: *bool = @ptrCast(apc_context); |
| 8301 | | flag.* = true; |
| 8302 | | _ = io_status_block; |
| 8303 | | _ = unused; |
| 8304 | 8301 | } |
| 8305 | 8302 | |
| 8306 | 8303 | fn fileReadPositionalPosix(file: File, data: []const []u8, offset: u64) File.ReadPositionalError!usize { |
| ... | ... | @@ -14407,7 +14404,7 @@ fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE { |
| 14407 | 14404 | t.mutex.lock(); // Another thread might have won the race. |
| 14408 | 14405 | defer t.mutex.unlock(); |
| 14409 | 14406 | if (t.random_file.handle) |prev_handle| { |
| 14410 | | _ = windows.ntdll.NtClose(fresh_handle); |
| 14407 | windows.CloseHandle(fresh_handle); |
| 14411 | 14408 | return prev_handle; |
| 14412 | 14409 | } else { |
| 14413 | 14410 | t.random_file.handle = fresh_handle; |