Skip to content

test(providers): stop the loopback stub inheriting non-blocking mode - #199

Merged
volen-silo merged 1 commit into
mainfrom
fix/loopback-test-server-blocking
Aug 12, 2026
Merged

volen-silo merged 1 commit into
mainfrom
fix/loopback-test-server-blocking

Conversation

@volen-silo

Copy link
Copy Markdown
Collaborator
  • If this PR fixes a bug, searched tests/e2e-cucumber/expectations.toml for the fixed ticket ID and removed/narrowed any now-stale xfail rows. (Not applicable — unit-test infrastructure.)

Problem

windows-build-and-test fails intermittently on PRs that touch nothing related, with a provider test dying on:

Error: A non-blocking socket operation could not be completed immediately. (os error 10035)
   6: rocm::providers::tests::request_complete::{{closure}}::{{closure}}
   7: rocm::providers::tests::spawn_models_only_server::{{closure}}

os error 10035 is WSAEWOULDBLOCK. Seen most recently on #196, which only changes a VRAM warning.

Root cause

spawn_models_only_server binds a non-blocking listener so its accept loop can poll the stop channel between connections. On Windows an accepted socket inherits the listener's non-blocking mode, so the first read of the request returns WSAEWOULDBLOCK instead of waiting. read_http_request propagates that, the server thread dies, and whichever test owned the server fails.

It is intermittent rather than constant because it depends on whether the request bytes have already landed in the socket buffer by the time the read runs — which is why it reads as an unrelated flake rather than a deterministic bug.

This is the same defect ec2bcb3 (#174) fixed in the e2e loopback server; that fix did not reach the stub this crate owns.

Fix

Put each accepted connection back into blocking mode. The existing two-second read timeout is what bounds the read — the non-blocking mode was only ever wanted on the listener, for the accept poll.

Test plan

cargo fmt --check and cargo clippy -p rocm --all-targets -- -D warnings clean. The providers suite run 6× in a row: 27 pass each time.

Not verified locally: the Windows behaviour itself. This host is Linux, where accept() returns a blocking socket regardless, so the bug does not reproduce here and the fix cannot be observed to work. The mechanism is documented Windows socket behaviour and matches both the stack trace above and the precedent in #174 — but the real confirmation is windows-build-and-test on this PR.

Worth noting the Linux-side flake I hit separately on local_provider_default_chat_requires_builtin_qwen_assistant is not explained by this and is still open — POSIX accept() returns a blocking socket, so that one has a different cause.

The models-only test server binds a non-blocking listener so its accept
loop can poll for the stop signal between connections. On Windows the
accepted socket inherits that mode, so the first read of the request
returns WSAEWOULDBLOCK (os error 10035) rather than waiting, the server
thread dies, and whichever provider test owned it fails.

It fails intermittently rather than always because it depends on whether
the request has already landed in the socket buffer by the time the read
runs, which is why this surfaces as an unrelated-looking flake on
windows-build-and-test.

Put each accepted connection back into blocking mode; the two-second read
timeout is what bounds the read. Same fix as the e2e loopback server got
in #174, applied to the stub this crate owns.

Signed-off-by: Eugene Volen <Eugene.Volen@amd.com>
@juhovainio

Copy link
Copy Markdown
Collaborator

Reviewed this. The fix is correct and minimal: putting the accepted connection back into blocking mode before the read is exactly the right place, since the non-blocking mode is only needed on the listener for the stop-channel poll, and the two-second read timeout already bounds the blocking read. It also mirrors the precedent fix in #174 (same WSAEWOULDBLOCK-on-Windows-inherited-socket issue in the e2e loopback server) closely enough that I'd be surprised if this doesn't fix it the same way.

I can't verify the Windows behavior locally either (same limitation the PR description calls out), but the code and reasoning check out from a diff-only read. Looks safe to approve pending a green windows-build-and-test run on this PR.

@volen-silo
volen-silo added this pull request to the merge queue Aug 12, 2026
Merged via the queue into main with commit 6527bae Aug 12, 2026
23 checks passed
@volen-silo
volen-silo deleted the fix/loopback-test-server-blocking branch August 12, 2026 13:48
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.

2 participants