Skip to content

test(ffi): order pending connect cancellation in place - #6034

Merged
kixelated merged 5 commits into
mainfrom
quest/m1/test-flakes-2/ffi-cancel-connect
Oct 20, 2026
Merged

kixelated merged 5 commits into
mainfrom
quest/m1/test-flakes-2/ffi-cancel-connect

Conversation

@kixelated

@kixelated kixelated commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

client_cancel_aborts_a_pending_connect flakes under load with assertion failed: matches!(connect_err, Err(MoqError::Cancelled)).

Root cause, reproduced: the dial can establish a session even though the server never calls accept(). The old fixture spawned connect, polled it once, then waited for the FFI runtime to catch up before calling cancel(). Under load the spawned task was repolled during that wait and returned Ok(session) before the cancel landed. With the old fixture plus a diagnostic print, 7 of 3840 runs (48 concurrent, host load around 50) failed, every one with connect returned Ok("session").

Approach

Dial a bound UDP socket that never answers (WebSocket fallback disabled) instead of a real server, so no handshake can finish before cancel(). Poll the foreign connect in place, assert the first poll is Pending, cancel synchronously, then resume it. Task::run checks the cancel flag first (biased select) on its next poll, so Cancelled wins by construction. Both assertions print what the connect actually returned.

A real server is not enough even when polled in place: the dial is spawned on the multithreaded FFI runtime, so a test thread preempted before its first established() check could see a finished handshake (Codex finding, fixed).

The quest is complete and deleted: the race is confirmed, the test no longer depends on it, and a cancel losing to a connect that already completed is correct production behavior, not a bug.

Impact

  • Public API and wire: none. Test-only ordering; production cancellation is unchanged.

Validation

  • Same host, same load (load average 40 to 56), same binary build flow:
    • Original fixture: 1920/1920 at 8 concurrent, 3833/3840 at 48 concurrent (7 failures, all Ok("session")).
    • In-place poll against the real server: 960/960 at 8 concurrent, 3840/3840 at 48 concurrent.
    • Final fixture (silent peer): 3840/3840 at 48 concurrent (load average around 27).
  • just check and quest check passed.
  • Earlier round: explicit native interop passed (five wire preflights, 32 publisher/subscriber cells, denial, FETCH, finite tails, Lite05/06 drop lanes). Browser interop was blocked by Chromium missing libglib-2.0.so.0; Swift was unavailable.

Decisions

No maintainer decision was given; the recommended option was picked.

  1. Quest after this PR
    • ✅ Delete it: the failure is reproduced and explained, and the fixture is deterministic by construction.
    • Keep it open for more loaded-host runs. Rejected: the root cause is known, so more runs add nothing.
  2. Keeping the connect pending (Codex finding)
    • ✅ A silent peer: a bound socket that never answers, so pending is a property of the peer, not of timing.
    • A test-only gate inside the dial. Rejected: adds a hook to production code for a test.
  3. Production change
    • ✅ None: a connect that resolves before cancel() legitimately returns its session.
    • Make cancel() revoke an already-returned session. Rejected: changes semantics with no behavioral benefit.

Follow-ups

None required. The other spawn_parked callers park calls that cannot complete before their trigger (a held lock, or a read with nothing to read), so none showed this gap.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 2 commits October 19, 2026 19:12
Co-Authored-By: GPT-6.1-Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1-Sol <noreply@openai.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Checkpoint: 366379772af4b2d6a9e74e39a7972df341e0c1bf. Strengthened only the pending-connect test's ordering and error diagnostics; public API, wire, and production cancellation behavior are unchanged.

The controlled helper diagnostic proved completion before cancel is permitted. It does not reproduce the historical 2/960 failure: the original and ordered fixtures each passed 128/128 bounded repetitions on an unsaturated host. The quest remains open for the unknown historical error/root cause and loaded-host acceptance.

Standard scoped checks passed, including 232 FFI and 102 Python tests. All 32 explicit native interop cells, five preflights, denial/FETCH/tails/drop lanes passed. Browser interop is blocked by Chromium1248 missing libglib-2.0.so.0; Swift was unavailable. All owned check/interop commands ended, exact harness children were reaped, and the port lease was released. Keep draft under the user's no-merge hold.

(written by GPT-6.1-Sol)

The old fixture reproduced under load (7 of 3840, all Ok(session)): the
dial establishes without the server accepting, so a spawned connect can
finish before cancel. The in-place poll is deterministic, so the quest
is done.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review October 20, 2026 05:35
@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 21 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2dde22ed-4a1e-415c-81d3-e3697c8d40e1
📥 Commits

Reviewing files that changed from the base of the PR and between 5284d96 and 0ab8faa.

📒 Files selected for processing: 3
  • quest/m1/test-flakes-2/README.md
  • quest/m1/test-flakes-2/ffi-cancel-connect.md
  • rs/moq-ffi/src/test.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T16:17:45.685614Z 0ab8faa New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cbd821be59

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-ffi/src/test.rs
A real server lets the handshake finish without accepting, so a dial
preempted between spawning and its first established() check could
resolve on the first poll. A bound socket that never answers keeps the
connect pending until cancel, with no handshake to race.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated added this pull request to the merge queue Oct 20, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 20, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit 05dcbaa Oct 20, 2026
4 checks passed
@kixelated
kixelated deleted the quest/m1/test-flakes-2/ffi-cancel-connect branch October 20, 2026 17:08
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