[PD] Gate disagg event loops on _engine_paused; reject pause(retract) in PD - #23672
Merged
Merged
Conversation
… in PD In PD-disaggregated mode, pause_generation does not actually quiesce the engine and can leave the scheduler in an inconsistent state: 1. event_loop_normal_disagg_prefill, event_loop_overlap_disagg_prefill, event_loop_normal_disagg_decode, and event_loop_overlap_disagg_decode never check self._engine_paused. They keep popping bootstrap queues, draining KV transfer queues, building batches, and running forwards while the engine is supposedly paused. As a result, mode="in_place" is effectively a no-op in PD and cannot serve as a weight-sync barrier. 2. mode="retract" partially retracts decode-side requests into disagg_decode_prealloc_queue, but there is no mechanism to send them back to the prefill node for re-prefill. A subsequent flush_cache then crashes inside RadixCache.dec_lock_ref because requests in disagg_prefill_inflight_queue still hold tree locks across the radix-tree reset. This patch: - Adds `if self._engine_paused: continue` immediately after process_input_requests in both PD prefill and PD decode event loops, mirroring the unified-mode pattern. Control RPCs continue to be processed while paused, but no scheduler-visible state transitions occur until continue_generation. - Asserts early in Scheduler.pause_generation that mode="retract" is unsupported when disaggregation_mode != NULL, before mutating any scheduler state. A proper fix requires a decode-to-prefill rebootstrap protocol; until then, failing fast is preferable to partial state changes followed by a delayed crash inside radix-cache cleanup. - Updates the pause_generation unit test fixture to set disaggregation_mode = NULL so existing retract-mode tests keep exercising the unified-mode path. Made-with: Cursor
ByronHsu
requested review from
ShangmingCai,
Ying1123,
hnyls2002,
merrymercy and
xiezhq-hermann
as code owners
April 24, 2026 19:57
Contributor
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
Comment on lines
+434
to
438
| if self._engine_paused: | ||
| continue | ||
| self.waiting_queue.extend( | ||
| self.disagg_prefill_bootstrap_queue.pop_bootstrapped() | ||
| ) |
Collaborator
There was a problem hiding this comment.
Should we bypass pop_bootstrapped on the prefill side? Will it cause the bootstrapping timeout for some requests when pausing generation?
Collaborator
Author
There was a problem hiding this comment.
I think this is unlikely to happen for now because timeout is 300s but weight sync usually under 30s. I will follow up if i meet similar issue in real run.
Collaborator
Author
There was a problem hiding this comment.
#23886 addressed here and fixed the conflicts
This was referenced Apr 27, 2026
5 tasks
5 tasks
yueming-yuan
pushed a commit
that referenced
this pull request
May 21, 2026
JessicaJiang-123
pushed a commit
to JessicaJiang-123/sglang
that referenced
this pull request
Jun 21, 2026
nanjiangwill
pushed a commit
to nanjiangwill/sglang
that referenced
this pull request
Jul 7, 2026
XinyuJiangCMU
pushed a commit
to XinyuJiangCMU/sglang
that referenced
this pull request
Jul 17, 2026
…gl-project#23887) Kept only the net-new delta on v0.5.15: fail-fast assertion in pause_generation + unit-test disaggregation_mode setup. The decode.py whitespace and inline test_pause_resume_in_place are dropped (v0.5.15 covers them via PauseResumeInPlaceMixin).
yueming-yuan
pushed a commit
that referenced
this pull request
Jul 25, 2026
yueming-yuan
pushed a commit
that referenced
this pull request
Jul 25, 2026
yueming-yuan
pushed a commit
that referenced
this pull request
Jul 25, 2026
yueming-yuan
pushed a commit
that referenced
this pull request
Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why?
In PD-disaggregated mode,
pause_generationdoes not actually quiesce the engine and can leave the scheduler in an inconsistent state:The disagg event loops (
event_loop_normal_disagg_prefill,event_loop_overlap_disagg_prefill,event_loop_normal_disagg_decode,event_loop_overlap_disagg_decode) never checkself._engine_paused. They keep popping bootstrap queues, draining KV transfer queues, building batches, and running forwards while the engine is supposedly paused. As a result,mode="in_place"is effectively a no-op in PD and cannot serve as a weight-sync barrier.mode="retract"partially retracts decode-side requests intodisagg_decode_prealloc_queue, but there is no mechanism to send them back to the prefill node for re-prefill. A subsequentflush_cachethen crashes insideRadixCache.dec_lock_refbecause requests still indisagg_prefill_inflight_queuehold tree locks across the radix-tree reset:How?
if self._engine_paused: continueimmediately afterprocess_input_requestsin both PD prefill and PD decode event loops, mirroring the unified-mode pattern. Control RPCs continue to be processed while paused, but no scheduler-visible state transitions occur untilcontinue_generation.Scheduler.pause_generationthatmode="retract"is unsupported whendisaggregation_mode != NULL, before mutating any scheduler state. A proper fix requires a decode-to-prefill rebootstrap protocol that does not exist yet; until then, failing fast is preferable to partial state changes followed by a delayed crash inside radix-cache cleanup.pause_generationunit-test fixture to setdisaggregation_mode = NULLso the existing retract-mode tests keep exercising the unified-mode path.Made with Cursor