Repository navigation
Conversation
Cached per-endpoint PUSH sockets are shared by transfer worker and bootstrap threads, but send_multipart was called without a lock. pyzmq sockets are not thread-safe, so concurrent sends can interleave message parts and corrupt the stream. On the decode side this shows up as malformed AUX_DATA killing decode_thread (mass 300s KV timeouts), or corrupted aux buffers causing a CUDA launch failure on one rank while the remaining ranks spin forever in the MoE A2A combine kernel. Add a per-endpoint send lock and route the four unlocked sender paths (status sync, aux data, chunk ready, abort ack) through it, matching the existing (sock, lock) pattern used by _connect_to_bootstrap_server.
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
We hit the same root cause in production, but with a different crash signature — sharing our case as additional evidence. Environment: GLM-based model, PD disaggregation with Mooncake backend, 2-node deployment (prefill TP16 + decode TP16), sgl-model-gateway as router. Symptom: The whole decode instance became permanently unavailable (100% reproducible until restart). Every request deterministically failed on TP rank 7 with: All other ranks then failed with Root cause investigation:
So this is the same bug as the Two suggestions:
|
Motivation
The mooncake KV manager caches one ZMQ PUSH socket per destination endpoint (
CommonKVManager._connect), and this socket is shared by all sender threads on the prefill side (up toSGLANG_DISAGGREGATION_THREAD_POOL_SIZEtransfer workers plus the bootstrap thread).send_multipartis called on the shared socket without any lock. pyzmq sockets are not thread-safe, so concurrent sends can interleave the parts of two multipart messages and corrupt the stream.Depending on how the corrupted message lands on the decode side, this causes:
decode_threaddies withstruct.error: unpack requires a buffer of 4 bytesin_handle_aux_data, after which all in-flight transfers on that rank hitKVTransferError ... timed out after 300.0s in KVPoll.WaitingForInput;CUDA error: unspecified launch failureon one rank while the remaining EP ranks spin forever at 100% GPU in the MoE A2A combine kernel — the whole decode worker appears deadlocked until the watchdog kills it.The probability scales with request rate and sender-thread count. On a 1P1D setup (Kimi-K2.5-NVFP4, decode TP8/EP8/DP8 across 2 GB300 nodes, streaming, concurrency 8192) it reproduced within minutes on every run; cuda-gdb on the hung ranks showed 7 ranks spinning in
moeA2ACombineKernelwaiting for the one rank whose context had faulted.Note the decode→prefill direction already handles this:
_connect_to_bootstrap_serverreturns(sock, lock)and all its callers send under the lock. This PR applies the same discipline to the prefill→decode direction.Modifications
common/conn.py: maintain a per-endpoint send lock next to the socket cache and add_send_multipart_locked.mooncake/conn.py: route the four unlocked sender paths (transfer status sync, aux data,CHUNK_READY,ABORT_ACK) through it.Verification
On the reproducer above (previously failed 3/3 within 4–8 min), the patched build completed 40960/40960 requests over 12 min with zero
struct.error/ launch failures / KV timeouts, at unchanged throughput (52.2k output tok/s, TPOT 27.2 ms).Motivation
Modifications
Accuracy Tests
Speed Tests and Profiling
Checklist
Review and Merge Process
/tag-and-rerun-ci,/tag-run-ci-label,/rerun-failed-ciCI States
Latest PR Test (Base): ❌ Run #28627692160
Latest PR Test (Extra): ❌ Run #28627692097