Isolate the stdio server's stdin and stdout from handler subprocesses (#3117)

This commit is contained in:
Max 2026-07-25 13:05:51 +01:00 • committed by GitHub
commit 629ca297d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 811 additions and 169 deletions

View file

@ -3919,9 +3919,12 @@ REQUIREMENTS: dict[str, Requirement] = {
note="Only observable over stdio: stdin/stdout purity is stdio-specific.",
divergence=Divergence(
note=(
"stdio_server's own writes satisfy this, but it does not redirect or guard sys.stdout: "
"handler code that calls print() writes directly to the protocol stream and corrupts the "
"framing. The spec MUST is satisfied only as long as application code behaves."
"While serving, stdio_server moves the wire to private descriptors and diverts fd 0/1, so "
"handler code and its child processes can neither read protocol bytes nor write into the "
"stream (pinned by tests/server/test_stdio.py). Remaining gaps: output flushed to stdout "
"before the transport enters can still precede the first frame, and the claim is "
"best-effort - skipped for explicitly injected streams and for processes without "
"normal standard descriptors."
),
),
),

View file

@ -114,7 +114,8 @@ async def test_stdio_server_writes_one_jsonrpc_message_per_line() -> None:
"""Every `stdio_server` write is one valid JSON-RPC message on its own line.
Each line is newline-terminated with payload newlines JSON-escaped. This proves the
transport's own framing; it does not guard `sys.stdout` against handler code (see the
transport's own framing over injected streams; the descriptor-level guard that keeps
handler code off the wire is pinned by tests/server/test_stdio.py (see the narrowed
divergence on `transport:stdio:stream-purity`).
"""
captured = io.StringIO()