Skip to content

Commit

Permalink
wasi: sockets, ensure overlapped I/O is handled correctly
Browse files Browse the repository at this point in the history
Signed-off-by: Edoardo Vacchi <[email protected]>
  • Loading branch information
evacchi committed Jan 7, 2024
1 parent e6f0904 commit cd50173
Showing 1 changed file with 29 additions and 4 deletions.
33 changes: 29 additions & 4 deletions internal/sysfs/file_windows.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sysfs

import (
"errors"
"syscall"
"unsafe"

Expand All @@ -10,12 +11,17 @@ import (
const (
nonBlockingFileReadSupported = true
nonBlockingFileWriteSupported = false

_ERROR_IO_INCOMPLETE = syscall.Errno(996)
)

var kernel32 = syscall.NewLazyDLL("kernel32.dll")

// procPeekNamedPipe is the syscall.LazyProc in kernel32 for PeekNamedPipe
var procPeekNamedPipe = kernel32.NewProc("PeekNamedPipe")
var (
procPeekNamedPipe = kernel32.NewProc("PeekNamedPipe")
procGetOverlappedResult = kernel32.NewProc("GetOverlappedResult")
)

// readFd returns ENOSYS on unsupported platforms.
//
Expand Down Expand Up @@ -50,8 +56,11 @@ func readSocket(h uintptr, buf []byte) (int, sys.Errno) {
var overlapped syscall.Overlapped
var done uint32
errno := syscall.ReadFile(syscall.Handle(h), buf, &done, &overlapped)
if errno == syscall.ERROR_IO_PENDING {
errno = sys.EAGAIN
if errors.Is(errno, syscall.ERROR_IO_PENDING) {
done, errno = getOverlappedResult(syscall.Handle(h), &overlapped, false)
if errors.Is(errno, _ERROR_IO_INCOMPLETE) {
return int(done), sys.EAGAIN
}
}
return int(done), sys.UnwrapOSError(errno)
}
Expand All @@ -60,12 +69,28 @@ func writeSocket(fd uintptr, buf []byte) (int, sys.Errno) {
var done uint32
var overlapped syscall.Overlapped
errno := syscall.WriteFile(syscall.Handle(fd), buf, &done, &overlapped)
if errno == syscall.ERROR_IO_PENDING {
if errors.Is(errno, syscall.ERROR_IO_PENDING) {
errno = syscall.EAGAIN
}
return int(done), sys.UnwrapOSError(errno)
}

func getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, wait bool) (uint32, syscall.Errno) {
var totalBytesAvail uint32
var bwait uintptr
if wait {
bwait = -1

Check failure on line 82 in internal/sysfs/file_windows.go

View workflow job for this annotation

GitHub Actions / Pre-commit check

cannot use -1 (untyped int constant) as uintptr value in assignment (overflows)

Check failure on line 82 in internal/sysfs/file_windows.go

View workflow job for this annotation

GitHub Actions / amd64, windows-2022, Go-1.21

cannot use -1 (untyped int constant) as uintptr value in assignment (overflows)

Check failure on line 82 in internal/sysfs/file_windows.go

View workflow job for this annotation

GitHub Actions / wasi-testsuite (windows-2022)

cannot use -1 (untyped int constant) as uintptr value in assignment (overflows)

Check failure on line 82 in internal/sysfs/file_windows.go

View workflow job for this annotation

GitHub Actions / amd64, windows-2022, Go-1.19

cannot use -1 (untyped int constant) as uintptr value in assignment (overflows)
}
totalBytesPtr := unsafe.Pointer(&totalBytesAvail)
_, _, errno := syscall.SyscallN(
procGetOverlappedResult.Addr(),
uintptr(handle), // [in] HANDLE hFile,
uintptr(unsafe.Pointer(overlapped)), // [in] LPOVERLAPPED lpOverlapped,
uintptr(totalBytesPtr), // [out] LPDWORD lpNumberOfBytesTransferred,
bwait) // [in] BOOL bWait
return totalBytesAvail, errno
}

// peekNamedPipe partially exposes PeekNamedPipe from the Win32 API
// see https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe
func peekNamedPipe(handle syscall.Handle) (uint32, syscall.Errno) {
Expand Down

0 comments on commit cd50173

Please sign in to comment.