Skip to content

fix(scheduler): wait for rank subscribers before first broadcast - #495

Open
Cyber-Marty wants to merge 1 commit into
FlashML-org:mainfrom
Cyber-Marty:fix/rank-broadcast-slow-joiner
Open

Cyber-Marty wants to merge 1 commit into
FlashML-org:mainfrom
Cyber-Marty:fix/rank-broadcast-slow-joiner

Conversation

@Cyber-Marty

Copy link
Copy Markdown

Fixes #364.

Root cause

A ZeroMQ slow-joiner race with a deadlock twist. In the TP>1 path, the SUB side's connect + SUBSCRIBE complete asynchronously, and nothing in the current setup waits for the registration to land on the publisher. If rank 0 picks up the first request and broadcasts before rank 1's subscription is registered on the PUB socket, ZMQ silently drops the message (PUB has no queue for unregistered peers). Rank 0 then waits for rank 1's reply, rank 1 waits for the next broadcast, and both ranks block forever while /v1/models keeps answering.

Fix

Switch the rank-0 broadcast socket from PUB to XPUB, which sends identically to PUB but surfaces inbound subscription events (first byte 0x01). The scheduler's broadcast path now calls wait_for_subscribers(tp_info.size - 1) before entering the receive loop, with a 30s timeout so a rank that died before connecting fails fast with a clear error instead of hanging the publisher silently.

Tests

tests/utils/test_mp_pubsub.py, 4 cases over real loopback TCP sockets:

  • first broadcast delivered after wait_for_subscribers, payload decoded equal
  • wait_for_subscribers(0) returns immediately (TP=1 behavior unchanged)
  • timeout raises TimeoutError without subscribers
  • msgpack byte roundtrip through put_raw is identical (XPUB does not change the wire format)

Red/green verified: all 4 fail on unpatched main (the new API does not exist), all 4 pass after the fix.

Tested on

Windows 11, CPU only, no multi-GPU box - pytest over real loopback TCP sockets (PYTHONPATH=python .venv/Scripts/python.exe -m pytest tests/utils/test_mp_pubsub.py). I could not run the full TP=2 serve path end to end; the race window itself is covered by the socket-level tests rather than an end-to-end run.

JUNQINGV587 added a commit to JUNQINGV587/FreeToken that referenced this pull request Sep 23, 2026
…broadcast

The TP control channel broadcasts the first message right after startup, but a SUB's
subscription only reaches the publisher asynchronously; anything broadcast before it
lands is silently dropped and both ranks block forever. Switches PUB to XPUB and waits
for size-1 subscription events. This fork runs TP=2 in production, so the race is live.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant