future: Add regression test for double callback#470
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR adds a regression test Sequence Diagram(s)sequenceDiagram
participant TestThread as TestThread
participant Tokio as TokioRuntime
participant Worker as spawn_blocking
participant CassFuture as CassFuture
participant Callback as counting_cb
TestThread->>Tokio: create multi-threaded runtime
TestThread->>Tokio: submit iteration task
Tokio->>Worker: spawn_blocking (create & resolve future with Barrier)
Worker->>CassFuture: resolve future (after Barrier)
TestThread->>CassFuture: cass_future_set_callback(counting_cb)
CassFuture->>Callback: invoke counting_cb (once)
TestThread->>CassFuture: cass_future_wait()
Possibly related PRs
Suggested labelsP1, area/Driver_-_cpp-rs-driver 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Pull request overview
Adds a Rust unit regression test to guard against the previously fixed race where a CassFuture callback could be invoked twice when cass_future_set_callback races with future resolution (refs #468 / issue #468).
Changes:
- Introduces a new multi-threaded, contention-based test that attempts to race
set_callbackagainst resolution and asserts the callback counter never exceeds 1. - Uses a barrier + blocking task to widen the race window and repeats the scenario many times to increase the chance of exercising the interleaving.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// (but not yet acquired the state lock to store it) by the time | ||
| /// `set_callback` is called, creating lock contention. | ||
| #[test] | ||
| #[ntest::timeout(30000)] |
| .into(), | ||
| ); | ||
|
|
||
| for _ in 0..10_000 { |
| /// To trigger this, we ensure the async task has already produced its result | ||
| /// (but not yet acquired the state lock to store it) by the time | ||
| /// `set_callback` is called, creating lock contention. |
| unsafe { cass_future_wait(cass_fut.borrow()) }; | ||
|
|
||
| // Spin-wait for the callback to be invoked at least once. | ||
| let deadline = std::time::Instant::now() + Duration::from_millis(100); |
Add a probabilistic test that verifies the callback is invoked exactly once when set_callback races with future resolution. The test creates a future whose resolution is synchronized via a barrier, then calls set_callback at the same time, checking that the atomic callback counter never exceeds 1. The natural race window is unfortunately too narrow to hit reliably without instrumentation. Manual testing on my machine showed the bug in ~20-40% runs, so this is enough to be hit in the CI from time to time.
872285d to
86331f3
Compare
Refs: #468 Add a probabilistic test (authored by Claude Opus 4.6) that verifies the callback is invoked exactly once when set_callback races with future resolution. The test creates a future whose resolution is synchronized via a barrier, then calls set_callback at the same time, checking that the atomic callback counter never exceeds 1. The natural race window is unfortunately too narrow to hit reliably without instrumentation. Manual testing on my machine showed the bug in ~20-40% runs, so this is enough to be hit in the CI from time to time. (cherry picked from commit ab2ce69)
Refs: #468
Add a probabilistic test (authored by Claude Opus 4.6) that verifies the callback is invoked exactly once when set_callback races with future resolution. The test creates a future whose resolution is synchronized via a barrier, then calls set_callback at the same time, checking that the atomic callback counter never exceeds 1.
The natural race window is unfortunately too narrow to hit reliably without instrumentation. Manual testing on my machine showed the bug in ~20-40% runs, so this is enough to be hit in the CI from time to time.
Pre-review checklist
[ ] I have enabled appropriate tests inMakefilein{SCYLLA,CASSANDRA}_(NO_VALGRIND_)TEST_FILTER.[ ] I added appropriateFixes:annotations to PR description.