[https://nvbugs/5961736][fix] Prebuild disagg ctx response to avoid ctx_request_id race#12466
Conversation
…capture The ctx response (containing ctx_request_id and opaque KV state) was only accessible while the request was in DISAGG_CONTEXT_TRANS_IN_PROGRESS. _check_disagg_ctx_cache_transfer_status(0) could advance the state to DISAGG_CONTEXT_COMPLETE before _handle_responses ran, causing C++ createResult() to return nullopt and leaving ctx_request_id=None. Fix: eagerly call create_response() immediately after respond_and_send_async() in _send_kv_async, while TRANS_IN_PROGRESS is guaranteed. The response is latched on the request (_eager_ctx_response) and consumed directly by _handle_responses, which skips create_response() for those requests. Safety of calling releaseState() here: CacheFormatter::format() (the CTX-side KV sender) reads only mRequestId, mSamplingConfig, getContextProgress(), and KV block data — it does NOT read mContextPhaseParams. The opaque state is only needed by the GEN-side unformat(), which runs in a separate process. Lifecycle is preserved: _handle_responses removes the request from active_requests (does not re-add to new_active_requests) without calling _terminate_request, leaving termination to _check_disagg_ctx_cache_transfer_status in both the in-flight (Case A) and already-complete (Case B) cases. Signed-off-by: peihengh <259410613+peihu-nv@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughModified response handling in the PyExecutor to capture and store context-only responses upfront during asynchronous KV transfer, then reuse the prebuilt response during response processing while adjusting termination logic to prevent duplicate request termination. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
/bot run |
1 similar comment
|
/bot run |
|
PR_Github #40146 [ run ] triggered by Bot. Commit: |
|
PR_Github #40146 [ run ] completed with state
|
|
/bot run |
|
PR_Github #40156 [ run ] triggered by Bot. Commit: |
|
PR_Github #40156 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #40168 [ run ] triggered by Bot. Commit: |
|
PR_Github #40168 [ run ] completed with state
|
…eateResult fix When the KV transfer poll in _send_kv_async advanced request state to DISAGG_CONTEXT_COMPLETE before _handle_responses ran, createResult() returned nullopt (its disagg-ctx branch only fired for TRANS_IN_PROGRESS), causing ctx_request_id=None and the error "Invalid disaggregated params in context phase response." Fix: - isFinished(): extend to cover DISAGG_CONTEXT_COMPLETE so createResult() passes the early-return guard for that state. - createResult(): broaden the disagg-ctx branch condition from isDisaggContextTransmissionState() to also match isDisaggContextCompleteState(), so the context phase params are included in the response regardless of which state the race resolves to. mContextPhaseParams is still valid at this point since releaseState() is called by createResult() itself. - py_executor.py _handle_responses(): guard the requests_to_terminate logic to skip DISAGG_CONTEXT_COMPLETE requests (already terminated by _check_disagg_ctx_cache_transfer_status), preventing double-free. Track them in requests_finished_by_transfer for stats visibility. Signed-off-by: peihengh <259410613+peihu-nv@users.noreply.github.com>
…lt with DISAGG_CONTEXT_COMPLETE Adds a unit test that constructs a context-only request in kDISAGG_CONTEXT_COMPLETE state and verifies createResult() returns a valid response with contextPhaseParams populated. Uses nullptr for the opaque state — sufficient to prove the fix (the bug was createResult() returning nullopt, not state pointer corruption). A follow-up could strengthen this with a non-null sentinel state and firstGenTokens check. Signed-off-by: peihengh <259410613+peihu-nv@users.noreply.github.com>
|
/bot run |
|
PR_Github #41027 [ run ] triggered by Bot. Commit: |
|
PR_Github #41027 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #41232 [ run ] triggered by Bot. Commit: |
|
PR_Github #41232 [ run ] completed with state
|
|
/bot run |
|
/bot run --disable-fail-fast |
|
PR_Github #41336 [ run ] triggered by Bot. Commit: |
|
PR_Github #41336 [ run ] completed with state |
|
/bot run --disable-fail-fast |
|
PR_Github #42171 [ run ] triggered by Bot. Commit: |
|
PR_Github #42171 [ run ] completed with state |
…tx_request_id race (NVIDIA#12466) Signed-off-by: peihengh <259410613+peihu-nv@users.noreply.github.com>
Summary by CodeRabbit
Bug Fixes
Performance
Description
Fixes a race in disaggregated serving where the CTX response can reach the orchestrator with ctx_request_id=None, causing a 500 error.
Root cause: _check_disagg_ctx_cache_transfer_status(0) in _send_kv_async() can advance a ctx-only request from DISAGG_CONTEXT_TRANS_IN_PROGRESS to DISAGG_CONTEXT_COMPLETE before _handle_responses() runs. Once that happens, C++ createResult() returns nullopt for contextPhaseParams, so the CTX response no longer carries ctx_request_id.
Fix: call create_response() immediately after respond_and_send_async() while the request is still guaranteed to be in the transfer-in-progress state, store the result as _prebuilt_ctx_response, and consume it later in _handle_responses() without calling create_response() again.
Test Coverage
N/A
PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.
GitHub Bot Help
To see a list of available CI bot commands, please comment
/bot help.