Fix stack CC request lifetime races - #529
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughThe PR updates CC request error and abort control flow, adds synchronization for stack-owned requests dispatched to shards, documents ownership and cancellation requirements, and advances the eloqstore submodule reference. ChangesCC request lifetime and completion
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tx_service/include/cc/cc_request.h`:
- Around line 7959-7962: The completion state in UploadRangeSlicesCc and
UploadBatchSlicesCc must be lock-free: replace mutex/condition-variable
signaling with atomic finish flags, make err_code_ atomic where required, and
update Wait() to poll with bthread_usleep exponential backoff. Remove all mutex
locking from ValidTermCheck and SetError, including UploadRangeSlicesCc at
tx_service/include/cc/cc_request.h:7959-7962 and UploadBatchSlicesCc at
tx_service/include/cc/cc_request.h:8220-8221 and 8243-8244; the latter site
requires SetError to be completely lock-free.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e1b01708-9c43-48a9-99bb-fb25b7e99d05
📒 Files selected for processing (4)
docs/03-concurrency-control.mdtx_service/include/cc/cc_request.htx_service/include/cc/template_cc_map.htx_service/src/cc/local_cc_shards.cpp
Context
This fixes a lifetime race in stack-owned CC requests observed while debugging the EloqKV main-branch CI crash.
CcShard::ProcessRequests()keeps a raw request pointer inreq_buf_, callsExecute(), and callsreq->Free()whenExecute()returnstrue. Some stack-owned requests signal their waiter from insideExecute()before that scheduler-sideFree()happens. The waiting thread can then reuse or destroy the stack object whileProcessRequests()still has the pointer.The concrete crash path is
KickoutCcEntryCc:SetFinish()callsres_->SetFinished(), the background worker wakes up and resets the stack request for the next table/node group, and the CC worker then returns toProcessRequests()and callsFree()on the same object.Behavior before and after
Before:
KickoutCcEntryCcrequests inLocalCcShards::PurgeDeletedData()andKickoutDataForTest()waited only forCcHandlerResultcompletion.UploadRangeSlicesCcandUploadBatchSlicesCcerror paths could returntrueor callFree()after waking their stack-owner waiter.After:
KickoutCcEntryCcrequests mark themselves in use before enqueueing and wait forInUse() == falseafter business completion, so the stack owner does not reset or destroy the object until scheduler-sideFree()is complete.false/ avoidFree(), matching their normal completion paths.Compatibility: pooled CC request behavior is unchanged.
Implementation
WaitForStackCcRequestFree()inlocal_cc_shards.cppusingbthread_usleep()bounded backoff against the existingCcRequestBase::InUse()flag.Use()before enqueueing the two stackKickoutCcEntryCcinstances and wait for scheduler-side free after the result callback has fired.UploadRangeSlicesCcandUploadBatchSlicesCcstack-owned error paths to complete the waiter without returningtruetoProcessRequests().UploadBatchSlicesCccache-reject path inTemplateCcMapto returnfalseafter setting the error.Design decisions and alternatives
This keeps the fix local to the unsafe stack-owned requests instead of changing the generic CC scheduler contract.
Use()/InUse()is already the scheduler-side ownership signal, so the stack request can use it as a final lifetime fence without adding a new request subclass or another flag.The wait happens outside
Execute()and outside CC worker threads. It uses bthread sleep/backoff instead of blocking inside the coroutine execution model.Test plan
Commands and results:
Full EloqKV TCL/CI tests were not run locally.
Risk assessment
The main regression surface is stack
KickoutCcEntryCccallers waiting slightly longer after logical completion. The wait should normally be short because it only covers the gap betweenSetFinished()andProcessRequests()callingFree(), and it backs off withbthread_usleep().Range upload changes intentionally affect stack-owned request paths; pooled request recycling remains unchanged.
Rollback plan
Revert this PR. That restores the previous request lifetime behavior.
Reviewer guide
tx_service/src/cc/local_cc_shards.cpp: stackKickoutCcEntryCclifetime fence.tx_service/include/cc/cc_request.h: stack range upload error/abort paths.tx_service/include/cc/template_cc_map.h: batch upload reject path.docs/03-concurrency-control.md: documented request lifetime invariant.Follow-up work
Run the full EloqKV GitHub Actions matrix after the parent EloqKV submodule pointer is updated.
Summary by CodeRabbit