Skip to content

fix(scheduler): check host write-back capacity before mutating retrac…#688

Open
alexps9 wants to merge 9 commits into
lightseekorg:mainfrom
alexps9:fix/scheduleretract-mutate-before-capacity-check
Open

fix(scheduler): check host write-back capacity before mutating retrac…#688
alexps9 wants to merge 9 commits into
lightseekorg:mainfrom
alexps9:fix/scheduleretract-mutate-before-capacity-check

Conversation

@alexps9

@alexps9 alexps9 commented Jul 15, 2026

Copy link
Copy Markdown

Problem

Scheduler::scheduleRetract() moves a request's local KV pages into the shared device prefix cache before verifying that enough host capacity is available for the corresponding write-back:

request->TakeFirstPages(alloc_count);
kv_prefix_cache_.Insert<ResourceType::Device>(...);

If EnsureCapacityByEvict<ResourceType::Host>() subsequently fails, the function returns without creating or applying the ScheduleRetractEvent that updates the request's device_node_ref_.

This leaves the request and prefix cache out of sync:

  • the request's local allocator has already released the pages;
  • the shared prefix-cache tree owns them under a deeper node;
  • the request still references the previous node.

This can cause a later OwnedPages::TakeFirst: count out of range failure or leave device pages permanently unreachable.

Other scheduling paths in this file perform all capacity checks before mutating allocator or cache state. scheduleRetract() was the exception.

Fix

Reorder scheduleRetract() so that it:

  1. Computes the host-side prefix match and required host pages.
  2. Calls EnsureCapacityByEvict<ResourceType::Host>().
  3. Transfers and inserts the device pages only after the capacity check succeeds.

The host-side match is independent of the device insertion, since Insert<ResourceType::Device>() only modifies the device resource state.

Testing

Added:

RetractHostCapacityExhaustedSuite.FailedHostCapacityCheck_DoesNotLeakDevicePages

The test exhausts the host page pool, forces the host-capacity check to fail, and verifies that all device pages are reclaimed after the requests finish or abort.

  • Before the fix: the expected device page is not reclaimed.
  • After the fix: exactly one device page is reclaimed.
  • Full C++ test suite: 408/408 passed.

Test plan

  • cmake --build . --target tokenspeed_scheduler_tests
  • Regression test fails on main and passes with this change
  • Full tokenspeed_scheduler_tests suite passes

…t state

Scheduler::scheduleRetract() called TakeFirstPages()/Insert<Device>() to
move a request's local KV pages into the shared prefix-cache tree
*before* checking EnsureCapacityByEvict<Host>() for the corresponding
write-back. When that host-capacity check failed, the function bailed
out via `return {}` — but the mutation had already happened, and the
ScheduleRetractEvent that would reconcile the request's
device_node_ref_ with the newly inserted tree node was never
constructed or applied. This leaves the request internally
inconsistent (its local allocator already shrunk, the tree already
owning pages the request's own bookkeeping doesn't know about), which
can later surface as an unrelated "OwnedPages::TakeFirst: count out of
range" crash or a permanently leaked device page.

Every other scheduleXxx() in this file (scheduleDecode,
scheduleDecodeFromRetracted, ...) already follows a strict
"check every capacity gate first, mutate only once all gates pass"
rule. Bring scheduleRetract() in line with that pattern: compute the
host match/capacity requirement first, and only take/insert the device
pages once EnsureCapacityByEvict<Host>() succeeds.

Added a regression test (RetractHostCapacityExhaustedSuite) that
forces a retract to hit an exhausted host pool and asserts the device
page ledger is fully consistent afterwards. Verified the new test
fails against the previous ordering (0 pages reclaimed instead of 1)
and passes with the fix; the full C++ suite (408 tests) passes.

Signed-off-by: alexps9 <alexps9@users.noreply.github.com>
@alexps9
alexps9 requested a review from a team as a code owner July 15, 2026 17:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 488e9b595e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread tokenspeed-scheduler/tests/cpp/test_retract_abort_pages.cpp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant