Skip to content

Re-arm SocketAddress.Size before every ReceiveFrom (fixes the red net8.0 leg) - #1

Merged
rowan-claude merged 1 commit into
mainfrom
fix-net8-receivefrom-socketaddress
Aug 7, 2026
Merged

rowan-claude merged 1 commit into
mainfrom
fix-net8-receivefrom-socketaddress

Conversation

@rowan-claude

Copy link
Copy Markdown
Collaborator

Fixes the one red CI on main (383666e): both OS legs fail deterministically in test_client_server_ipv4_socket_connect with ArgumentOutOfRangeException: Provided SocketAddress is too small for given AddressFamily at Socket.ReceiveFrom, via NetcodeSocket.ReceivePacket.

Mechanism (read straight from the runtime source, release/8.0 vs release/9.0 Socket.cs): the SocketAddress-taking ReceiveFrom overload guards receivedAddress.Size >= SocketAddress.GetMaximumAddressSize(AddressFamily) before every call. On .NET 8 it then assigns receivedAddress.Size = socketAddressSize before checking the recvfrom result, so the first empty poll of our non-blocking socket (EWOULDBLOCK, the steady state) zeroes Size, and the next call trips the guard. .NET 9 moved that assignment below the error check, which is exactly why the net10 leg is green and only the LTS leg burns.

Fix: one field store at the top of ReceivePacket — re-arm _receiveAddress.Size to the family maximum before each call. No allocation (the zero-allocation steady-state test still passes).

Verified locally: dotnet build tests/Tests.csproj -c Release (both TFMs, warnings-as-errors, clean) and both test legs, 46/46 each. Caveat stated plainly: this machine has only the .NET 10 runtime, so the net8.0 TFM ran under DOTNET_ROLL_FORWARD=LatestMajor — which is precisely why the defect never showed locally. This PR exists so CI's real .NET 8 proves the fix before it lands on main.

… whole again

The receive path now survives empty polls on .NET 8. Socket.ReceiveFrom
requires the reusable SocketAddress sized to the family maximum before
each call, and .NET 8 overwrites Size with the received address length
BEFORE checking the recvfrom result - so the first EWOULDBLOCK poll (the
steady state of a non-blocking socket) zeroes it and the next call throws
ArgumentOutOfRangeException "SocketAddress is too small" out of
NetcodeSocket.ReceivePacket. .NET 9 moved that assignment below the error
check, which is why only the LTS leg failed. Local runs cannot see this:
the net8.0 TFM rolls forward to the .NET 10 runtime here, so both legs
(46 tests each) pass locally and CI's real .NET 8 is the proof that counts.
@rowan-claude
rowan-claude merged commit 1941d8a into main Aug 7, 2026
4 checks passed
@rowan-claude
rowan-claude deleted the fix-net8-receivefrom-socketaddress branch August 7, 2026 21:03
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