Repository navigation
[Bugfix][TransferEngine] Pin BatchDesc across completion callbacks before freeBatchID - #4569
Conversation
…eBatchID Terminal slice counters become visible to waiters while the completion callback is still unwinding inside finishIfComplete, so a racing freeBatchID could delete the BatchDesc and its TransferTask objects (heap-use-after-free observed under ASan in tcp_write_visibility_test). Hold an RAII pin on the BatchDesc for the whole callback in all builds (previously EDC-only and incremented after the first task dereference), and make freeBatchID/tryFreeBatchID defer deletion until the pin count drains. Also set batch_id in TcpTransport::submitTransfer like every sibling transport so direct-Transport submissions get the same protection, drop a post-unpin slice write in HCCL, stop the deferred-cleanup loop from retrying permanent errors forever, and let tests accept the now-legal BatchCleanupDeferred outcome. Fixes kvcache-ai#4556
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
koriyoshi2041
left a comment
There was a problem hiding this comment.
Reviewed exact head 50414ff4 against the #4556 failure ordering. The lifetime acquisition now precedes every terminal publication (markSuccess, markFailed, and submission sealing), while both direct and multi-transport free paths require the pin count to drain. That closes the check-then-enter window without making TCP a special case.
The hosted CTest job is green. The two generic wheel reds are not in this diff: both runners were shut down with exit 137 while building the unrelated PG PyTorch extension; the CUDA/EFA/ROCm and transfer-engine lanes passed. I did not find a separate correctness gap in this head.
Description
Fix the use-after-free reported in #4556:
Slice::markSuccess()/markFailed()publish the terminal slice counters and then keep dereferencing task/batch state insidefinishIfComplete(), while a racingfreeBatchID()could already delete theBatchDescand theTransferTaskobjects it owns (ASan: heap-use-after-free atSlice::markSuccessintcp_write_visibility_test). Theactive_completion_callbacksquiescence counter previously existed only underUSE_EVENT_DRIVEN_COMPLETION(off by default) and was incremented insidefinishIfCompleteafter the firsttask->dereference — a check-then-enter gap in every build.What this changes:
BatchDescwith an RAII guard at the top ofmarkSuccess/markFailed/sealTaskSubmission, before any terminal state is published; the pin drops when the callback unwinds.BatchDesc::active_completion_callbacksunconditional so non-EDC builds get the same protection.Transport::freeBatchID/MultiTransport::tryFreeBatchIDreturnBatchBusywhile pins are held; engine callers already convert that intoBatchCleanupDeferredhandled by the existing deferred-cleanup thread — no new machinery.TcpTransport::submitTransfernow setstask.batch_idlike every sibling transport, so direct-Transport submissions get the same pin protection.slice->statusstore aftermarkFailedin HCCL (it landed after the pin was released).freeBatchIDassertions accept the now-legalBatchCleanupDeferredoutcome.The intermittent ECONNRESET at the WRITE-ack read is consistent with this race in the shared-process loopback (freed slab reuse corrupting sibling state); if it recurs without an ASan signature it should be tracked as a separate TCP flake.
Credit to @koriyoshi2041 for the lifetime-analysis in the issue that pinpointed the retention boundary.
Module
mooncake-transfer-engine)mooncake-store)mooncake-conductor)mooncake-reshard)mooncake-ep)mooncake-pg)mooncake-integration)mooncake-p2p-store)mooncake-wheel)mooncake-common)mooncake-rl)Type of Change
How Has This Been Tested?
Test commands:
Test results:
Checklist
./scripts/code_format.shAI Assistance Disclosure
AI assistance disclosure: this fix was implemented with AI assistance; the reproduction, the test results, and every changed line were verified by the human submitter.