Repository navigation
Bind the MessageQueue remote socket atomically - #42695
Merged
Merged
Conversation
When several MessageQueue writers with remote readers start at the same time on one host, get_open_port() can hand two of them the same port: it only probes for a free port, and the later remote_socket.bind() is a separate step. The loser dies in __init__ with "zmq.error.ZMQError: Address already in use", taking down the process group it was initializing. Replace the probe-then-bind pair with pyzmq's bind_to_random_port, which binds atomically and retries on EADDRINUSE. The search window starts at the probed port and spans 32 ports, so SGLANG_PORT still anchors the port range; exhausting the window raises ZMQBindError. The IPv6 socket option is still set before the bind, and the exported handle carries the port that was actually bound. The local socket already binds this way. Co-authored-by: charlotte12l <charlotte12l@users.noreply.github.com>
metamergebot
requested review from
ch-wan,
merrymercy and
yizhang2077
as code owners
October 6, 2026 02:00
Collaborator
Author
|
This port clears our bar on gate 20✓✗2✂4 lint✓ build 3✓✗1✂3 A✓ B✓ C 0/8⏳ other 6✓✂6 · accel ✗amd,npu,xpu @merrymercy @charlotte12l — could one of you take a look and merge it if you are happy? Nothing else is waiting on our side. |
hanming-lu
approved these changes
Oct 6, 2026
This was referenced Oct 7, 2026
cursor Bot
pushed a commit
to cipheraxat/sglang
that referenced
this pull request
Oct 9, 2026
Co-authored-by: merrymercy <merrymercy@users.noreply.github.com> Co-authored-by: charlotte12l <charlotte12l@users.noreply.github.com>
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.
Motivation
MessageQueue.__init__sets up the remote XPUB socket in two steps:get_open_port()probes for a free port, thenremote_socket.bind()claims it. Nothing holds the port in between. When several writers with remote readers are created concurrently on one host (for example, multi-node model-parallel groups that each build a broadcaster during initialization), two of them can be handed the same port, and the later one dies in__init__:The failing rank takes its whole process group down with it. #29455 closed this window for the local socket; the remote socket still has it. #15903 proposed moving both sockets onto
get_zmq_socketas a wider refactor, but it has been in conflict withmainfor months.Modifications
shm_broadcast.py: replace the probe-then-bind pair for the remote socket with pyzmq'sbind_to_random_port, which binds atomically and retries onEADDRINUSE. The window starts at the portget_open_port()returned and spans 32 ports, soSGLANG_PORTstill anchors the range and the ephemeral fallback is unchanged. Exhausting the window raisesZMQBindError.IPV6is still set before binding, and the exported handle carries the port that was actually bound.Accuracy Tests
Not applicable: only the way the remote broadcast socket picks its port at initialization changes.
Speed Tests and Profiling
Not applicable: initialization only, nothing on the request path.
Test plan
CPU-only script outside the repo that imports the real
shm_broadcastandnetworkmodules, run against this branch and againstmain, for IPv4 and IPv6:get_open_portis patched to return a port another socket already holds.mainraisesZMQError(EADDRINUSE)from__init__; this branch binds another port inside the window.mainthree of the four fail withEADDRINUSE; on this branch all four bind distinct ports inside the window.wait_until_ready,enqueue,dequeue) still delivers.ZMQBindError.ruff,ruff-format,isortandcodespellat the versions pinned in.pre-commit-config.yamlpass on the changed file.Checklist
CI States
Latest PR Test (Base): 🚫 Run #37401987293
Latest PR Test (Extra): ❌ Run #37402003034
Latest PR Test (AMD ROCm 10): ❌ Run #37401987257