Proper handling async IO for WIN32

Even given OVERLAPPED, functions like ReadFile/WriteFile
still MAY complete before they return. In that case,
we should not call GetOverlappedResult, and should respect
the numberOfBytes output from the original IO function.
This commit is contained in:
hsfzxjy 2025-07-20 01:00:23 +08:00
parent 61d5df6e6d
commit e7e5856b83
No known key found for this signature in database
GPG key ID: 279C22B7DBCCFB94
4 changed files with 6 additions and 9 deletions

View file

@ -68,7 +68,7 @@ static textwindows ssize_t ntspawn_read(intptr_t fh, char *buf, size_t len) {
uint32_t got;
struct NtOverlapped overlap = {.hEvent = CreateEvent(0, 0, 0, 0)};
ok = overlap.hEvent &&
(ReadFile(fh, buf, len, 0, &overlap) ||
(ReadFile(fh, buf, len, &got, &overlap) ||
GetLastError() == kNtErrorIoPending) &&
GetOverlappedResult(fh, &overlap, &got, true);
if (overlap.hEvent)

View file

@ -93,7 +93,8 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
// initiate asynchronous i/o operation with win32
struct NtOverlapped overlap = {.hEvent = event, .Pointer = offset};
bool32 ok = ReadOrWriteFile(handle, data, size, 0, &overlap);
uint32_t exchanged = 0;
bool32 ok = ReadOrWriteFile(handle, data, size, &exchanged, &overlap);
if (!ok && GetLastError() == kNtErrorIoPending) {
if (f->flags & _O_NONBLOCK) {
// immediately back out of blocking i/o if non-blocking
@ -135,11 +136,8 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
CancelIoEx(handle, &overlap);
}
}
ok = true;
}
uint32_t exchanged = 0;
if (ok)
ok = GetOverlappedResult(handle, &overlap, &exchanged, true);
}
uint32_t io_error = GetLastError();
CloseHandle(event);

View file

@ -81,7 +81,7 @@ textwindows int IsWindowsExecutable(int64_t handle, const char16_t *path) {
BLOCK_SIGNALS;
struct NtOverlapped overlap = {.hEvent = CreateEvent(0, 0, 0, 0)};
ok = overlap.hEvent &&
(ReadFile(handle, buf, 2, 0, &overlap) ||
(ReadFile(handle, buf, 2, &got, &overlap) ||
GetLastError() == kNtErrorIoPending) &&
GetOverlappedResult(handle, &overlap, &got, true);
CloseHandle(overlap.hEvent);

View file

@ -362,8 +362,7 @@ ABI void klog(const char *b, size_t n) {
struct NtOverlapped overlap = {.hEvent = ev};
ok = !!__imp_WriteFile(h, b, n, 0, &overlap);
if (!ok && __imp_GetLastError() == kNtErrorIoPending)
ok = true;
ok &= !!__imp_GetOverlappedResult(h, &overlap, &wrote, true);
ok = !!__imp_GetOverlappedResult(h, &overlap, &wrote, true);
if (!ok)
__klog_handle = 0;
__imp_CloseHandle(ev);