Fix max new tokens - #772
Merged
Merged
Conversation
timethink
pushed a commit
to timethink/sglang
that referenced
this pull request
Mar 9, 2025
amote-i
pushed a commit
to amote-i/sglang
that referenced
this pull request
Dec 8, 2025
<!-- Thank you for your contribution! Please follow these guidelines to enhance your pull request. If anything is unclear, submit your PR and reach out to maintainers for assistance. Join our Slack community at https://slack.sglang.ai to discuss further. --> ## Motivation <!-- Describe the purpose and goals of this pull request. --> ## Modifications <!-- Detail the changes made in this pull request. --> ## Accuracy Tests <!-- If this pull request affects model outputs (e.g., changes to the kernel or model forward code), provide accuracy test results. --> ## Benchmarking and Profiling <!-- If this pull request impacts inference speed, provide benchmarking and profiling results. --> ## Checklist - [ ] Format your code according to the [Format code with pre-commit](https://docs.sglang.ai/developer_guide/contribution_guide.html#format-code-with-pre-commit). - [ ] Add unit tests according to the [Run and add unit tests](https://docs.sglang.ai/developer_guide/contribution_guide.html#run-and-add-unit-tests). - [ ] Update documentation according to [Write documentations](https://docs.sglang.ai/developer_guide/contribution_guide.html#write-documentations). - [ ] Provide accuracy and speed benchmark results according to [Test the accuracy](https://docs.sglang.ai/developer_guide/contribution_guide.html#test-the-accuracy) and [Benchmark the speed](https://docs.sglang.ai/developer_guide/contribution_guide.html#benchmark-the-speed).
efschu
pushed a commit
to efschu/htsglang
that referenced
this pull request
Aug 19, 2026
THE CHECK WAS IN THE WRONG PLACE, NOT MISSING. write() already refuses at ENQUEUE via the sgl-project#718 device-tier disarm. The copy happens later, and the flip rebinds in between, so a write-back queued before a cutover reaches backup_from_device_all_layer carrying a pointer table into the pool it was built from. Both crash specimens died three seconds AFTER a pp_to_tp cutover completed: 14:08:14 -> 14:08:17 (epoch 27) and 07:12:09 -> 07:12:12 (epoch 3), seven hours apart, same direction, same lag. WHY THE SHAPE GUARD COULD NEVER CATCH IT, and why its silence was misread as innocence -- by me, until the operator pushed back. Under layer_first the host layout EQUALS the device layout, so a stale binding is shape-IDENTICAL to the live one and check_shapes passes by construction. That is exactly what sgl-project#760 recorded: KV-TRANSFER-GUARD armed on all three ranks, zero transfers refused, SIGSEGV anyway. Matching shapes plus a crash puts the fault below the Python seam; a generation stamp is what tells "same shape" from "same pool". MEASURED, ONE VARIABLE. HiCache host+disk under sustained 4-way load with the flip REMOVED (plain TP3, which keeps speculation on -- PP+spec requires the flip, server_args.py:18385) survives five minutes with 0 segfaults and 0 admission wedges, and passes the REP gate outright (1 distinct/12, salted 0/6). The fault needs the cutover. STAMPED BY CONSTRUCTION, VERIFIED AT CONSUME. The stamp lives in CacheOperation.__init__ rather than at one enqueue site: an op built by any other path would otherwise be unstamped, and an unstamped op must be refused, which silently dropped legitimate write-backs and broke the staged-dispatch tests until I moved it. A stale op is dropped loudly and counted; its prefix simply misses later, the same cheap failure the sgl-project#718 disarm already accepts. Also folded in, both consequences of earlier sgl-project#767 work rather than new choices: the anchor-protection test that encoded "no interval means no anchors" is updated to the corrected premise it was measured against, and the SECOND-PASS EVICTION line drops from warning to info -- the second pass is documented as legitimate, and anchor eviction was falsified as the drift cause, so it is accounting rather than an alarm. 4 new tests, red-first (a pre-rebind stamp must be refused). mem_cache and managers suites: 4047 passed, 43 failed -- all 43 the pre-existing sgl-project#772 class (PhasePolicyConfig lacks idle_locked_settle_s after the sgl-project#713 revert), one fewer than the 44 baseline because the 747 premise test is now correct. ruff clean on both touched files (0 at HEAD, 0 now).
efschu
pushed a commit
to efschu/htsglang
that referenced
this pull request
Aug 19, 2026
…at outlive their phase TWO HOLES, ONE WINDOW. The sgl-project#718 guard read the parallel_state routing global, which is toggled INSIDE the cutover -- one step among many -- so for the whole seam (waves moving KV rows, movers releasing the outgoing backing, the cutover rebuilding topology) the guard named a phase while pool bytes were in motion. And even a perfect predicate cannot recall a copy that is already riding the controller's private CUDA streams: write() and start_writing() run in the same Python instant (start_writing is called synchronously from write, its only caller), so the previous commit's consume-time re-check re-asks the question at the same moment it was first asked. The torn window is the STREAM's asynchrony, not the queue's: a device->host copy enqueued legitimately in PP outlives its Python call by seconds under load, and the seam releases the pool under it. Both crash specimens died exactly there -- 3 s after a pp_to_tp cutover, inside backup_from_device_all_layer, below the Python seam. THE FIX, in the two halves the window has: 1. AUTHORITY. PhaseFlipRuntime registers itself (weakly) as the phase guard's authority. Its _phase field is what the PHASE-FLIP DONE line reports -- truthful by the 3 s crash correlation -- and it alone knows the seam's extent: hicache_seam_active is raised at the no-return point (after the unanimous-abandon verdict, before the first wave) and cleared after the cutover installs the new phase, with a finally in the caller as insurance. During the seam the guard refuses device-tier I/O for EVERY binding. Outside it, the authority's phase wins over the routing global, and a disagreement logs the sgl-project#754-shape instrument line that settles whether that global was ever stale here. No authority registered (no flip runtime built) falls back to the routing global: non-flipping deployments stay byte-identical. 2. QUIESCE. At the same no-return point the runtime drains the controller's write_stream and load_stream while every pointer they hold still names live memory. Finishing those copies is correct (they become durable cache entries) and bounded (PCIe transfer of the backlog; this thread is the only device-tier producer, so nothing refills behind the drain; rank-local, so it cannot wedge the group). Ordered after the sgl-project#703 flip-writeback hook, whose staging copies are the largest legitimate producer of exactly such in-flight work. Tests: test_flip_seam_guard_760.py, 10 tests, red-first (all 10 fail on the parent commit: seam disarm and authority-wins are impossible there, quiesce/_quiesce_hicache do not exist). With the fix: 14/14 green including the sgl-project#760 stamp tests. Full mem_cache+managers sweep: 4057 passed, 43 failed -- the 43 are the pre-existing sgl-project#772 class (PhasePolicyConfig lacks idle_locked_settle_s), zero regressions, +10 passed vs the parent's 4047. ruff clean on the new code (the 13 E402 in cache_controller.py pre-exist on HEAD); codespell clean. Metal gate next: the 2-SIGSEGV repro arm must hold >=2 cutovers under 4-way load with 0 segfaults and logged seam refusals.
efschu
pushed a commit
to efschu/htsglang
that referenced
this pull request
Aug 19, 2026
…-- the hole the crash went through THE METAL FALSIFIED THE PREVIOUS COMMIT'S SUFFICIENCY IN 40 SECONDS, and the faulthandler stack it produced is the whole finding. seamfix1 (52df0ff, repro arm, 4-way load) registered the authority on all three ranks, quiesced at two seams, completed pp_to_tp epoch 3 -- and segfaulted seconds later in the TP phase, through a stack the guards never see: unified_radix_cache.cache_finished_req -> insert -> _inc_hit_count -> write_backup -> hybrid_cache/hybrid_cache_controller.write -> start_writing -> backup_from_device_all_layer -> transfer_kv_direct This deployment's tree cache is UnifiedRadixCache driving HybridCacheController -- which INHERITS from HiCacheController (so the seam quiesce worked, it is inherited) but OVERRIDES write() and load() without the device_tier_disarmed checks the base methods carry. Every sgl-project#718/sgl-project#760 metal reading of 'zero disarm hits' on this stack was therefore vacuous: the guarded methods never executed; TP-phase inserts enqueued copies against the PP-bound pools unchecked, and one of them walked released backing. The overrides now ask the guard first, before any pool is touched, with the base contract: refuse -> return None -> the caller books a miss (write_backup returns 0, load-back returns False -- both verified None-tolerant). Tests: two red-first additions to test_flip_seam_guard_760.py pin both overrides (an alloc-must-not-run pool proves the guard runs FIRST); both fail on the parent commit, 16/16 green with the fix. Full mem_cache+managers sweep: 4059 passed, 43 failed -- the pre-existing sgl-project#772 class only, zero regressions. ruff and codespell clean. Metal gate re-run next on this commit: >=2 cutovers under 4-way load, 0 SIGSEGV, and the first genuinely non-zero disarm/refusal counters on this stack.
efschu
pushed a commit
to efschu/htsglang
that referenced
this pull request
Aug 19, 2026
…s at the flip, write state bytes in the computing pool The sgl-project#767 round-2 residual (NOTE_735: 'the fourth cached hit degenerates and stays degenerate') rooted to two wrong-pool defects in the mamba checkpoint path of a phase-flip build, found via two new metal discriminators on boot 735_seamfix2 (39 epochs standing): - salted probes with a UNIQUE first token: 0/8 degenerate, serial; - salted probes sharing one lead token: ~10/12 degenerate, including one answered with a verbatim FOREIGN topic (the load run's river essay) that survived /flush_cache; - concurrent unique-lead probes: 2-3/8 degenerate with prompt-level bleed. So corruption enters exclusively where a prefix hit restores a mamba checkpoint, and the payload is stale pool bytes: 1. resident_mamba_slots() moved only live requests' slots at a cutover while the KV leg unions the radix tree's values. Every tree-held checkpoint kept its slot NUMBER across the flip while its CONTENT was never translated into the new layout's pool; the prefix-hit COW (model_runner._maybe_execute_deferred_mamba_cow_and_clear) then seeded fresh requests from whatever the active pool held at that slot. flip_mamba_slots() now unions the tree's mamba values, and refuses a tree that cannot enumerate them. 2. The radix caches' checkpoint copies (donate-copy in cache_unfinished, int8 store_from_active) ran through the tree's bound pool -- the primary PP stack's, forever -- while a TP-phase request's real state bytes live in the TP stack's pool. The copy therefore duplicated the PP tensor's stale previous occupant into the checkpoint even with no flip during the request's lifetime. State-byte operations now resolve the computing stack's pool (mamba_state_pool.active_mamba_state_pool, installed by build_gdn_flip_mover); slot bookkeeping stays single-authority on the bound pool. Non-flip builds have no resolver and keep the old path bit for bit. Excluded by prior metal falsifiers and this trace: the sgl-project#767 slot-carry branch (0 carry-without-copy logged, force-clear changed nothing), allocator divergence (single authority by construction), fresh-no-match prefill state reads (has_initial_states = extend_prefix_lens > 0), ping-pong track path (no_buffer on this shape), ReplaySSM (refused by gdn_flip_preconditions). Tests: test_gdn_flip_tree_slots_767.py (red-first: ImportError then 5 passed), test_mamba_checkpoint_active_pool_767.py (7 passed). mem_cache+managers suites: 4071 passed, 43 failed -- all the pre-existing sgl-project#772 PhasePolicyConfig class, plus the known env-dependent test_localslot_family_756 retry failure (fails identically on clean HEAD). Metal validation on the rebooted arm follows in the boot note.
efschu
pushed a commit
to efschu/htsglang
that referenced
this pull request
Aug 22, 2026
… loop it drives 7 failed / 7 passed -> 14 passed, exit 0. Completes the WIP commit. `_event_loop_pp_body` is taken unbound off the mixin here, so every link the body grew since sgl-project#791 had to exist on `_Rank`, and each one only became visible once the one above it was closed -- eleven in all across the two commits. The stub/bind split held throughout and is the part worth keeping: a shipped method is BOUND whenever it can answer without a peer, and STUBBED only where it would block on a real PP wire this fixture has no peer for, or dereference the None the link above returns. Every stub returns the shape the shipped function returns on its own no-op path, with that line quoted at the callsite, so none of them encodes a behaviour the production code does not have. The runtime flags (_pp_pass_voided_incoming, _pp_output_expected_incoming, _pp_upstream_launched_incoming, _pp_admission_pass_voided, _pp_gapped_wire) are set to the values a rank that received nothing carries, not to whatever made the next traceback go away. Standing observation, for whoever owns sgl-project#631: a harness that must re-declare every method its subject grows will break exactly like this again. Eleven links in one release is the signal, not the eleven fixes.
efschu
pushed a commit
to efschu/htsglang
that referenced
this pull request
Aug 23, 2026
…t#816, sgl-project#810, sgl-project#806, sgl-project#797, sgl-project#790/sgl-project#777, sgl-project#817/sgl-project#820, sgl-project#818 Merge-checklist duty for the nine stages on this branch. Entries follow each section's own house style, and the mechanism text is taken from the commits' measured evidence rather than restated from the ticket titles. §3 KV backing relief + the allocator cap -- UPDATED IN PLACE rather than given a second bullet, because sgl-project#814 and sgl-project#816 are follow-on defects OF the KvRowCap mechanism that bullet already describes: the census reading the withheld block as a leak (340262 of 465190 ids), the lift being reachable only from a cutover (one boot at 26.8% of its id space for the life of the process), and exposure exceeding the backing (417850 rows over 105413 committed, the device-side assert in masked_set_kv_buffer_kernel). §3 HiCache staging write-through ring (sgl-project#810), new bullet, plus its two companion refusals -- the unbounded-file-tier refusal and the boot preflight ledger entry, the latter being why 22.01 GB of MHATokenToKVPoolHost across three PP ranks previously reached the preflight as nothing. §7 BAR1 deadline + loud abort -- appended the sgl-project#818 peer-liveness half to the existing narrative: the gate could wait forever on a peer that no longer exists, and neither Bar1CollectiveStalled (reset by every resolved read) nor defer_stall_for_building_peer (900 s off a build marker) caught it. §12 Robustness canon -- three new families: contradictory-flag (sgl-project#806), read-back-after-construction (sgl-project#797), denylist-of-reasons (sgl-project#817, sgl-project#820). §18.3 hicache staging sizing (sgl-project#810) -- §18's own rule is that a merge adding a reusable module adds its entry in the SAME merge, and this module had none. Records the removal of fits_pinned_host_budget so it is not reintroduced. §18.6 mamba carry instrument (sgl-project#767, gated by sgl-project#790) and flip break-even N (sgl-project#777). No existing entry was contradicted. Checked before writing: none of sgl-project#814, sgl-project#810, sgl-project#806, sgl-project#772, sgl-project#797, sgl-project#790, sgl-project#777, sgl-project#817, sgl-project#820, sgl-project#818 had a catalog entry, and the one sgl-project#677 line (§19.2, RESTORE-NEVER-REBUILD) describes a different mechanism than the sgl-project#677 layout hold, so it is not stale and was left alone. Gates for the tree this documents (hermetic, CUDA_VISIBLE_DEVICES=""): battery test/registered/unit/{managers,planner,server_args,mem_cache} baseline integ @ 78d27da 44 failed c56d238 (through sgl-project#818) 30 failed, 8452 passed 0 new ids, 14 fixed 1c4eadb (through sgl-project#816) 30 failed, 8461 passed 0 new ids, same set test_barlink_abort_gate_liveness_818.py (outside the battery dirs) 10 passed ruff --select=F401,F821,UP037 and codespell: 0 new findings vs the same file set on 78d27da (16 ruff / 6 codespell exist identically on base) docs-only change; codespell clean on the catalog itself
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.
Fix the case of
max_new_tokens=0after #766