Skip to content

[coding_agent_rl] middleware: shutdown_session drains in-flight handl… - #1954

Merged
zhuzilin merged 2 commits into
THUDM:mainfrom
jingshenghang:coding-agent-rl-shutdown-session
May 27, 2026
Merged

zhuzilin merged 2 commits into
THUDM:mainfrom
jingshenghang:coding-agent-rl-shutdown-session

Conversation

@jingshenghang

Copy link
Copy Markdown
Collaborator

…ers before sglang release_memory_occupation

When a SWE rollout sample returns, slime's train loop immediately calls release_memory_occupation, which hard-asserts sglang's is_fully_idle(). Straggler claude-cli requests from the just-torn-down sandbox can still be in the sglang pipeline (running_batch / chunked_req / result_queue / hicache writes) at that exact moment, tripping the assert and SIGQUITing the scheduler subprocess. Every multi-step SWE RL run was crashing on the first offload after a rollout step.

Three-layer drain in the middleware (only examples/ touched, slime backend untouched):

  • module-level _inflight: dict[sid, set[Task]] tracks every running _handle_request; lives outside the Session dataclass so it survives pop_session_split
  • module-level _closed: set[sid] tombstones drained sids; _handle_request early-returns 503 for them so stragglers cannot silently setdefault a fresh Session and reach sglang
  • shutdown_session(store, sid):
    1. _closed.add(sid)
    2. asyncio.wait the in-flight bucket, cancel + gather pending
    3. sleep settle_sec=3.0 (sglang /abort_request is fire-and-forget IPC; takes several scheduler ticks to actually clear the batch)
    4. GET sglang_url/flush_cache?timeout=N -- sglang's own native idle-wait via _check_pending_flush, strictly stronger than the settle sleep
  • pop_session_split deliberately does NOT discard from _closed (permanent tombstone). sids are unique per rollout step so the set only grows linearly per process.
  • generate.py finally-block calls shutdown_session before pop_session_split; idempotent on the happy path.

Validated 2026-05-26 on 8-node Qwen3.6-35B-A3B SWE RL: step 0 (rollout_0

  • train + weight update + offload) and step 1 (rollout_1 + train, loss -1.03, grad_norm 3.36) both completed cleanly. Prior settle_sec=0.3 still raced intermittently; 3.0 + flush_cache double-check is stable.

…in-flight handlers before sglang release_memory_occupation

When a SWE rollout sample returns, slime's train loop will later call
release_memory_occupation, which hard-asserts sglang's `is_fully_idle()`
and SIGQUITs the scheduler on miss. Straggler claude-cli requests from
the just-torn-down sandbox can still reach sglang via middleware's
`setdefault(sid, Session())` at that moment, tripping the assert. Every
multi-step SWE RL run was crashing on the first offload after a rollout
step.

Two-layer close in the middleware (only examples/ touched, slime backend
untouched):

- module-level `_inflight: dict[sid, set[Task]]` tracks every running
  `_handle_request`; lives outside the Session dataclass so it survives
  `pop_session_split`
- module-level `_closed: set[sid]` tombstones drained sids;
  `_handle_request` early-returns 503 for them so stragglers cannot
  silently `setdefault` a fresh Session and reach sglang
- `shutdown_session(sid)`: `_closed.add(sid)`, then `asyncio.wait` the
  in-flight bucket, cancel + gather pending (cancel fires
  `/abort_request` to sglang via `_generate`'s cleanup)
- `pop_session_split` deliberately does NOT discard from `_closed`
  (permanent tombstone). sids are unique per rollout step so the set
  only grows linearly per process
- `generate.py` finally-block calls `shutdown_session` before
  `pop_session_split`; idempotent on the happy path

Does NOT wait for sglang idle here -- slime's
`sglang_engine.release_memory_occupation` already calls `flush_cache()`
with 60x1s polling (returns 200 only when scheduler is idle), strictly
stronger than anything we could probe from the middleware. Once
`_closed` is set and local handlers are drained, no new request can
reach sglang, so the backend's existing flush_cache covers the actual
idle wait.

Validated 2026-05-26 on 8-node Qwen3.6-35B-A3B SWE RL: step 0 (rollout
+ train + weight update + offload) and step 1 (rollout + train, loss
-1.03, grad_norm 3.36) both completed cleanly.
@jingshenghang
jingshenghang force-pushed the coding-agent-rl-shutdown-session branch from 22fa81f to 9c098ca Compare May 27, 2026 04:00
@zhuzilin
zhuzilin merged commit 8210124 into THUDM:main May 27, 2026
26 of 27 checks passed
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.

2 participants