feat(iouring): recv-arming witnesses (RecvResumeWhileRecvInFlight, RecvDoubleArmed, RecvCQEUnaccounted) and the BP-swept oracle that measured #484/#560 (celeris#586) - #597
Merged
Conversation
…t the BP that opens the #484 window Adds four engine-wide witnesses to the io_uring worker and exports them through engine.EngineMetrics, plus a per-conn recvOutstanding count: RecvResumeWhileCancelPending resume processed with recvCancelPending set RecvResumeWhileRecvInFlight ...and the cancelled recv still armed (the exact celeris#484 window; the pending flag alone also counts resumes after a cancel that MISSED, so it over-approximates ~1000x) RecvArmDeclined prepareRecv declined an arm (recvArmed) RecvDoubleArmed a second recv SQE placed on one conn (recvOutstanding reached 2), any site RecvCQEUnaccounted terminal recv CQE for a live conn with recvOutstanding == 0: a kernel-held recv the bookkeeping never counted. The only witness independent of cs.recvArmed. Direct atomic adds, not per-iteration batches: the batch flush runs before drainDetachQueue and is skipped when the loop returns, and these are per-event invariants where one event refutes. The WS484 oracle reads them after settle() and hard-asserts RecvDoubleArmed == 0 and RecvCQEUnaccounted == 0 on io_uring. Two new socketpair tests drive the real call sites (drainDetachQueue pause -> resume before any reap -> -ECANCELED re-arm -> data CQE), and the stale bookkeeping case the guard cannot see. Measured (docker golang:1.27, kernel 7.0.12-linuxkit, 4 cpus, memlock 128 MiB, workers=4 in every run, single-shot io_uring subtest ALONE, 96 conns x 4 bursts x 16000 frames, no -race). N=12 per build per BP; control = guard turned into a count + dirty-list guard reverted: BP build windows(InFlight) doubleArmed cqeUnaccounted parseErr PASS 8 control 12 in 9/12 runs 6441 0 11 (8 runs) 3/12 8 fixed 12 in 7/12 runs 0 0 0 12/12 16 control 6 in 5/12 2818 0 4 (4 runs) 7/12 16 fixed 9 in 3/12 0 0 0 12/12 32 control 9 in 3/12 6322 0 7 (3 runs) 9/12 32 fixed 4 in 3/12 0 0 0 12/12 256 control 0 in 0/12 0 0 0 12/12 256 fixed 0 in 0/12 0 0 0 12/12 1e6 both 0 0 0 0 24/24 8 stale 4 in 4/12 0 131760 4 (4 runs) 0/12 Chosen BP = 8. At the fixture default (256) neither build enters the window in 24 runs, so the pre-existing 0/24 vs 0/24 had no power. On the fixed tree at BP=8 the window is entered 12 times and RecvDoubleArmed and RecvCQEUnaccounted stay 0 with parseErr 0; on the control every window entry places a second recv and the twin recvs stay doubled for the rest of the connection (doubleArmed is amplified, armDeclined equals the window count) and 8 of 12 runs corrupt frames. The stale-bookkeeping build (recvArmed cleared after the pause cancel) corrupts frames in 4 of 12 runs with RecvDoubleArmed 0 in all of them and RecvCQEUnaccounted ~11000 per run: the kernel-side witness sees what the userspace guard cannot. Unit tests under -race: fixed tree 3/3 pass; control fails TestPrepareRecvRefusesSecondArm (pending 1->2) and TestResumeBeforeCancelLandsPlacesNoSecondRecv (doubleArmed 1); the stale build fails the honest window test and passes the witness test.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The counters and test changes that measured #586 (report and skeptic review on the issue; both skeptics accept the measurement).
connState.recvOutstandingtracks the two SQE placement sites against the terminal recv CQE;EngineMetricsgainsRecvResumeWhileCancelPending,RecvResumeWhileRecvInFlight(the narrow window witness),RecvArmDeclined,RecvDoubleArmedandRecvCQEUnaccounted(a terminal recv CQE the bookkeeping did not expect: the kernel-side witness of a double arm). One atomic op per event, none per request. The inbound-sequence oracle prints the counters after settle and hard-assertsRecvCQEUnaccounted == 0andRecvDoubleArmed == 0;WS484_BPis swept so the resume-during-cancel window is actually entered (at the fixture default of 256 neither build enters it in 24 runs).Measured: at BP=8 the fixed tree shows 12 window entries with 0 unaccounted / 0 double-armed / 0 parse errors in 12/12 runs, the guard-removed control shows 6441 placements and corrupts frames in 8/12 runs. Also exposed #596 (stale
recvCancelPending), fixed separately.