mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #4454] [Bug]: Handshake daemon can kill the whole process with SIGPIPE when a peer resets mid-reply #1128
Labels
No labels
ascend
auto-closed
bug
bug
CI/Build
Common
documentation
enhancement
feature request
good first issue
help wanted
high priority
MetaX
nightly-failure
pull-request
PyTorch Backend
question
RFC
Roadmap
stale
Store
Tests
Transfer Engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/Mooncake#1128
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @he-yufeng on GitHub (Oct 2, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/4454
The P2P handshake daemon answers every accepted frame with
writeString(conn_fd, ...)and then half-closes (the listener loop in transfer_metadata_plugin.cpp).writeStringgoes throughwriteFullyin common.h, a rawwrite()loop, and nothing in the transfer engine ignores SIGPIPE or sends with MSG_NOSIGNAL. If the peer resets the connection while the daemon is mid-reply (the client timed out and closed, crashed, or closed with reply bytes still unread), the daemon's nextwrite()raises SIGPIPE and the whole process dies. In a vLLM-style deployment that process is the transfer engine host, so one flaky peer can take down a worker.I hit this from the test side first: the flood test on #4453 closed each connection after a single bare
read(), which can return after just the frame header. When that happened while the daemon was still writing the payload, the test process died with SIGPIPE on the CTest leg. The daemon path is the samewriteStringwith untrusted peers on the RPC port, so the exposure is not test-only.Minimal repro against a running P2PHANDSHAKE daemon: connect, send one valid Notify frame, close immediately without reading; repeat until the reply write lands after the RST (load-dependent).
Two small directions:
writeFullytosend(..., MSG_NOSIGNAL)(SO_NOSIGPIPE setsockopt on macOS, which has no MSG_NOSIGNAL). Surgical, and it also hardens the client side, which uses the same helper.signal(SIGPIPE, SIG_IGN)), which covers every other socket write in the process too.Happy to send a PR once there is a preferred direction.
Environment: current main, Linux x86_64, first observed on the ubuntu-22.04 CTest leg.
@github-actions[bot] commented on GitHub (Oct 2, 2026):
Thanks for opening this issue, @he-yufeng!
40085740A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide