From 5afe8f9de95ac7e7466f299ef0aa37b6b8c49088 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 7 Nov 2026 23:01:56 -0800 Subject: [PATCH 1/2] chore(quest): claim quest/m0/test-flakes-2/qlog-staging-spin.md Quest-Claim: edf5dec12e049b1a From 33eb355476084153fcd2049af3743d343dce1f32 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Sat, 7 Nov 2026 23:10:33 -0800 Subject: [PATCH 2/2] test(moq-uring): run the qlog writer loop inline so accounting is settled Co-Authored-By: Claude Opus 5.5 --- quest/m0/test-flakes-2/README.md | 1 - quest/m0/test-flakes-2/qlog-staging-spin.md | 21 --------------- rs/moq-uring/src/quic/qlog.rs | 30 ++++++++++++++++----- 3 files changed, 23 insertions(+), 29 deletions(-) delete mode 100644 quest/m0/test-flakes-2/qlog-staging-spin.md diff --git a/quest/m0/test-flakes-2/README.md b/quest/m0/test-flakes-2/README.md index 6d554a41a6f..213cafad0e6 100644 --- a/quest/m0/test-flakes-2/README.md +++ b/quest/m0/test-flakes-2/README.md @@ -207,4 +207,3 @@ Public API: none. Wire: none. - [The http:// fingerprint tests survive a slow fetch](/quest/m0/test-flakes-2/fingerprint-host-clock.md) - a fingerprint fetch slower than the 500 ms hedge no longer trips the host-clock guard - [A lite-07 reply FINs instead of resetting when the subscriber FINs mid-write](/quest/m0/test-flakes-2/lite07-reply-fin.md) - `js/net`'s empty-window reply test passes under `--rerun-each 200`, fixed in the publisher - [moq-relay's forged-dial test waits for bob's endpoint](/quest/m0/test-flakes-2/forged-dial-announce.md) - `a_forged_dial_never_connects` requests bob's endpoint only after its announce reaches mallory, and its `#[ignore]` is removed -- [moq-uring's qlog accounting test waits on the accounting](/quest/m0/test-flakes-2/qlog-staging-spin.md) - `an_open_trace_accounts_for_staging_and_close` waits for the accounting, not 10,000 spins diff --git a/quest/m0/test-flakes-2/qlog-staging-spin.md b/quest/m0/test-flakes-2/qlog-staging-spin.md deleted file mode 100644 index f8c98e913f5..00000000000 --- a/quest/m0/test-flakes-2/qlog-staging-spin.md +++ /dev/null @@ -1,21 +0,0 @@ -# [XS] moq-uring's qlog accounting test waits on the accounting - -## Goal - -moq-uring's `quic::qlog::tests::an_open_trace_accounts_for_staging_and_close` -passes on a loaded host. It waits for the staged memory to be accounted, not -for a fixed number of spins. - -## Plan - -Planned 2026-11-07 (maintainer, /quest-complete), a follow-up of -[moq-dev/moq#8208](https://github.com/moq-dev/moq/pull/8208). - -The test (`rs/moq-uring/src/quic/qlog.rs`) spins up to 10,000 -`std::thread::yield_now` calls until `sink.inner.memory` reaches the -expected value, which a background thread sets. On a loaded host the thread -can run late and the spins run out first. Wait on the accounting itself, for -example a condition the sink signals when it charges memory, or a blocking -read of the staged state. Don't raise the spin count. - -Public API: none. Wire: none. diff --git a/rs/moq-uring/src/quic/qlog.rs b/rs/moq-uring/src/quic/qlog.rs index f9c86c39976..7e70d81f55d 100644 --- a/rs/moq-uring/src/quic/qlog.rs +++ b/rs/moq-uring/src/quic/qlog.rs @@ -399,20 +399,36 @@ mod tests { #[test] fn an_open_trace_accounts_for_staging_and_close() { + // Own the writer's channel and run its loop on this thread, so the + // accounting is settled when the loop returns rather than whenever a + // background thread gets scheduled. let dir = tempfile::tempdir().expect("temp dir"); - let sink = Sink::directory(dir.path()).expect("sink"); + let (tx, rx) = mpsc::channel(); + let sink = Sink { + inner: Arc::new(Inner { + dir: dir.path().to_path_buf(), + started: 0, + process: 0, + sink: 0, + tx: Some(tx), + memory: Arc::new(AtomicUsize::new(0)), + next: AtomicU64::new(0), + dropped: AtomicBool::new(false), + thread: None, + }), + }; let trace = sink.trace(Side::Server); + let (writer_tx, writer_rx) = mpsc::channel(); + writer_tx.send(rx.recv().expect("queued open")).expect("forward open"); + drop(writer_tx); + write_traces(writer_rx, &sink.inner.memory); + let accounted = CHUNK + std::mem::size_of::(); - for _ in 0..10_000 { - if sink.inner.memory.load(Ordering::Relaxed) == accounted { - break; - } - std::thread::yield_now(); - } assert_eq!(sink.inner.memory.load(Ordering::Relaxed), accounted); drop(trace); + assert_eq!(sink.inner.memory.load(Ordering::Relaxed), std::mem::size_of::()); drop(sink); }