Skip to content

implement Windows platform compatibility via WSAPoll and IOCP#60

Closed
qdsxinyee wants to merge 15 commits into
bemanproject:windows-supportfrom
qdsxinyee:fix/windows-platform-compat
Closed

implement Windows platform compatibility via WSAPoll and IOCP#60
qdsxinyee wants to merge 15 commits into
bemanproject:windows-supportfrom
qdsxinyee:fix/windows-platform-compat

Conversation

@qdsxinyee

Copy link
Copy Markdown

Description

This PR implements the core network capabilities for Windows platforms, addressing the missing Windows support mentioned in the project's current state. It is intended to be merged into the windows-support branch to finalize the cross-platform compatibility.

Key Implementations:

  1. Default Windows Backend (WSAPoll):
    • Provided a functional backend using WSAPoll for basic I/O polling, acting as a counterpart to the POSIX poll(2) implementation.
  2. High-Performance Backend (IOCP):
    • Added an I/O Completion Ports (IOCP) implementation for high-performance asynchronous networking on Windows.
    • This feature is placed behind a CMake feature flag to keep the default build straightforward. It can be enabled using -DBEMAN_NET_WITH_IOCP=ON.

How to test this locally (Windows):

Test default WSAPoll:

cmake --preset msvc-debug
cmake --build --preset msvc-debug
ctest --preset msvc-debug

Test IOCP backend:

cmake --preset msvc-debug  -DBEMAN_NET_WITH_IOCP=ON
cmake --build --preset msvc-debug
ctest --preset msvc-debug

- platform.hpp: add Windows compatibility shim
  - define iovec, msghdr, socklen_t, pollfd, nfds_t
  - map POSIX errno names to WSA equivalents
  - wrap close/fcntl/poll/recvmsg/sendmsg/getsockopt/setsockopt
  - undef interface macro to fix local_endpoint.hpp conflict

- netfwd.hpp: use uintptr_t for native_handle_type on Windows
  to avoid truncating 64-bit SOCKET values

- poll_context.hpp: replace errno with sock_errno()
  fix ::socket() return type handling for Windows

- internet.hpp: replace memcpy with explicit loop in constexpr
  constructor to satisfy MSVC constexpr rules

- io_context.hpp: add IOCP backend selection, guard SIGPIPE

- iocp_context.hpp: new IOCP backend implementation
  - AcceptEx / ConnectEx / WSARecv / WSASend async operations
  - iocp_op_kind tag for zero-RTTI completion dispatch
  - wsa_guard RAII for WSAStartup/WSACleanup

- CMakeLists.txt: add BEMAN_NET_WITH_IOCP option (Windows only)
- src/beman/net/CMakeLists.txt: link ws2_32/mswsock on Windows
Add iocp_context as the primary Windows io_context backend using I/O
Completion Ports (IOCP), and waspoll_context as a poll-based fallback.

iocp_context design:
- Each pending async operation is represented by an iocp_op embedding
  OVERLAPPED as its first member, recovered via reinterpret_cast on
  GQCS completion
- Synchronous completions (rc==0) are handled via deferred_io_task to
  avoid re-entering the dispatch call stack; FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
  is set on each socket to prevent the kernel posting a redundant IOCP
  packet for the same operation
- AcceptEx/ConnectEx loaded dynamically via WSAIoctl per socket
- Timers implemented as a sorted_list keyed on time_point, checked on
  every run_one() call
- d_socket_count tracked alongside d_outstanding_io to prevent
  premature event loop termination
- WSAStartup/WSACleanup managed by RAII wsa_guard

platform.hpp: add Windows-specific type aliases and Winsock includes
On Windows, accepted sockets are set non-blocking via set_nonblocking(),
causing add_outstanding() to invoke work() inline. If the operation
completes synchronously (e.g. async_send with data already buffered),
work() calls complete() internally, which decrements d_outstanding,
resumes the coroutine, and may destroy 	his before submit() returns.

The previous code unconditionally called this->complete() after submit()
returned ready, resulting in a heap-use-after-free detected by ASan.

Fix: on Windows, do not touch 	his after submit(). On POSIX, sockets
default to blocking so work() is never called inline; the explicit
this->complete() call is still required there.

Fixes: ASan heap-use-after-free in sender_state::start() / complete()
@qdsxinyee

Copy link
Copy Markdown
Author

Closing as upstream has added IOCP support in main. Thanks!

@qdsxinyee qdsxinyee closed this May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant