Skip to content

Wait for the OOB byte in IOControl_SIOCATMARK_Unix_Success - #135789

Merged
rzikm merged 2 commits into
dotnet:mainfrom
caraioniurie47:issue-135787
Oct 16, 2026
Merged

rzikm merged 2 commits into
dotnet:mainfrom
caraioniurie47:issue-135787

Conversation

@caraioniurie47

@caraioniurie47 caraioniurie47 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

IOControl_SIOCATMARK_Unix_Success sends an in-band byte and an out-of-band byte, then spins until SIOCATMARK is 0 to let the out-of-band byte arrive. On Unix SIOCATMARK is already 0 before any data arrives, so the spin can end at once. If the client then reads the in-band byte before the out-of-band byte has arrived, there is no mark yet, and the next assert sees SIOCATMARK == 0 instead of 1:

OSSupport.cs:149-151

                        // OOB data received, read pointer at mark.
                        Assert.Equal(4, client.IOControl(IOControlCode.OobDataRead, null, siocatmarkResult));
                        Assert.Equal(1, BitConverter.ToInt32(siocatmarkResult, 0));

The change: after the two sends, wait for the out-of-band byte with Socket.Select, the client in the error list and a 10 s timeout, and assert the client is still in the list. On Linux this polls for POLLPRI; on Apple platforms Socket.Select uses select, and on macOS its exception set reports pending out-of-band data. client.Poll(TimeSpan.FromSeconds(10), SelectMode.SelectError) is not used: on macOS it calls poll, which does not report out-of-band data as POLLPRI, and it timed out on both macOS CI legs that ran the test. Every existing assert is kept as it was. The existing spin now runs after the out-of-band byte has arrived, so its check of "OOB data received, but read pointer not at mark" applies to that state. The Windows test is not changed: it asserts SIOCATMARK is 1 before any data is sent, so its spin already waits for the out-of-band byte.

Spinning until SIOCATMARK is 1 after the in-band read also passed with the delay below. It was not taken because it turns the "read pointer at mark" assert into a wait, and the "not at mark" check would still run before the out-of-band byte arrives.

Tests: no test was added; the change is to the test itself. On Linux, holding only the loopback TCP segments with the URG flag for 20, 100 or 300 ms (an NFQUEUE helper and an iptables rule; see the issue) made the unchanged test fail at OSSupport.cs:151 with Expected: 1 / Actual: 0 in every run, and the changed test pass in every run. Without the delay, both pass. The Socket.Select version was not run on macOS or other non-Linux Unix platforms. On macOS CI, the Poll version timed out on OSX.15.Amd64.Open and OSX.26.Arm64.Open, where the unchanged test passes on main. The System.Net.Sockets functional tests (outer-loop tests excluded) pass on Linux with and without the change. The test project also builds for net11.0-windows.

Resolves #135787

Note

AI-generated, written at my direction and reviewed by me before posting.
Source read at dotnet/runtime 06b83f7.
Run on Ubuntu 22.04.5 LTS on WSL 2, Linux 6.18.40.1-microsoft-standard-WSL2 x64 (the runs of the Socket.Select version: 6.18.54.1), testhost shared framework 12.0.0 built with ./build.sh clr+libs -rc Release.
Commands: the same test run repeatedly through the testhost's xunit.console.dll at no delay and at 20, 100 and 300 ms, with and without the change, and with the spinning alternative; ./.dotnet/dotnet build src/libraries/System.Net.Sockets/tests/FunctionalTests /t:Test with and without the change; ./.dotnet/dotnet build src/libraries/System.Net.Sockets/tests/FunctionalTests -f net11.0-windows.
The macOS statements about poll and select come from reading XNU source (xnu-12377.1.9 and xnu-11215.81.4: poll and poll_callback in bsd/kern/sys_generic.c, filt_sorattach and filt_soread_common in bsd/kern/uipc_socket.c, soo_select in bsd/kern/sys_socket.c); the macOS results are from this PR's CI build 1635683 and from main builds of the same pipeline.
The Windows sentence comes from a Python probe on Windows 11 that calls Winsock's ioctlsocket(SIOCATMARK) on a loopback socket before any data, after the in-band byte and after the out-of-band byte (1, 1, 0); the .NET Windows test was not run.

On Unix, SIOCATMARK is 0 before any data arrives, so the test's
SpinUntil(SIOCATMARK == 0) after the server sends the in-band byte and
the out-of-band byte can return before either byte has reached the
client. When the client then reads the in-band byte before the
out-of-band byte arrives, the read pointer is not yet at a mark and the
next assert sees SIOCATMARK == 0 instead of 1.

Wait with Poll(SelectMode.SelectError), which reports the exceptional
condition that out-of-band data has arrived, before checking SIOCATMARK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Oct 14, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @karelz, @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

The test waited with Poll(SelectMode.SelectError), which on Unix polls
for POLLPRI. On macOS poll() does not report pending out-of-band data
as POLLPRI, so the wait timed out on macOS CI.

Wait with Socket.Select on the error list instead. It polls for POLLPRI
on Linux as before, and on Apple platforms it uses select(); on macOS
its exception set reports pending out-of-band data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rzikm
rzikm merged commit 24543dd into dotnet:main Oct 16, 2026
83 of 86 checks passed
@caraioniurie47
caraioniurie47 deleted the issue-135787 branch October 16, 2026 07:33
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.Net community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OSSupportTest.IOControl_SIOCATMARK_Unix_Success does not wait for the out-of-band byte

2 participants