From 12b15ceea299f1add53420b20e69802af9a02248 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Sun, 1 Nov 2026 02:32:12 +0100 Subject: [PATCH] test(quic): let the parked pool tasks leave before their flags go ShouldSendWithoutBlockingQUIC parked every pool worker on tasks that polled a release flag local to the block, and the block could end, the flag with it, within the millisecond a task takes to notice the release. The flags now live on the heap and the block waits for every parked task to leave. Co-Authored-By: Claude Opus 5.5 --- tests/ShouldSendWithoutBlockingQUIC/main.cpp | 22 +++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/ShouldSendWithoutBlockingQUIC/main.cpp b/tests/ShouldSendWithoutBlockingQUIC/main.cpp index 2e9fd93..0fbb8aa 100644 --- a/tests/ShouldSendWithoutBlockingQUIC/main.cpp +++ b/tests/ShouldSendWithoutBlockingQUIC/main.cpp @@ -178,16 +178,23 @@ int main() { // reader before the pool is parked. WaitFor([&] { return readersStarted.load() > before; }, std::chrono::seconds(10)); - std::atomic release = false; - std::atomic parked = 0; + // Leaked, and released only once every parked task has left, so + // none reads it after this block. + struct Parking { + std::atomic release = false; + std::atomic parked = 0; + std::atomic left = 0; + }; + Parking& parking = *new Parking; const unsigned workers = ThreadPool::activeThreads.load(); for (unsigned i = 0; i < workers * 2; ++i) { - ThreadPool::Enqueue([&] { - ++parked; - while (!release.load()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + ThreadPool::Enqueue([&parking] { + ++parking.parked; + while (!parking.release.load()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + ++parking.left; }); } - const bool allParked = WaitFor([&] { return parked.load() >= workers; }, std::chrono::seconds(10)); + const bool allParked = WaitFor([&] { return parking.parked.load() >= workers; }, std::chrono::seconds(10)); constexpr int links = 100; auto done = std::make_shared>(0); @@ -208,7 +215,8 @@ int main() { Check(allParked && finished && ok->load(), std::format("with all {} pool workers parked, a chain of {} sends, each from the last one's onSent, completed", workers, done->load())); - release = true; + parking.release = true; + WaitFor([&] { return parking.left.load() == workers * 2; }, std::chrono::seconds(10)); const bool arrived = WaitFor([&] { return received.Of('B').has_value(); }, std::chrono::seconds(10)); Check(arrived && FollowsPattern(*received.Of('B'), links), "and the peer read them all, in order"); *chain = nullptr;