Fix concurrent sendMessage race in StdioClientTransport by AbbasNS · Pull Request #876 · modelcontextprotocol/java-sdk
added 2 commits
March 20, 2026 15:11When two threads call sendMessage() concurrently on the same StdioClientTransport, the unicast sink's SinkManySerialized wrapper returns FAIL_NON_SERIALIZED via its CAS guard, causing "Failed to enqueue message". This test reproduces the race: 19/20 repetitions fail. Closes modelcontextprotocol#875
Replace tryEmitNext (fail-fast) with emitNext + busyLooping(100ms) in StdioClientTransport.sendMessage(). The unicast sink's SinkManySerialized wrapper returns FAIL_NON_SERIALIZED when two threads call tryEmitNext concurrently. busyLooping retries the CAS spin instead of immediately failing, making concurrent sends safe. The contention window is microseconds (single CAS operation), so the 100ms duration is just a generous upper bound for pathological cases like GC pauses. Before: 19/20 test repetitions fail After: 20/20 pass Closes modelcontextprotocol#875
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