From 6e1d268578162d45401da45b129ee0217f1b0871 Mon Sep 17 00:00:00 2001 From: xarmian Date: Tue, 29 Sep 2026 12:40:17 +0000 Subject: [PATCH] test(mcp): widen the EOF settle and state the pin's two bounds (TASK-3298) Codex round 2 on 5889ff62 (P2): the EOF signal fires inside Read, before the server handles EOF, so the release after it is a timed settle. A cancel-at-EOF server delayed past it would pass. Nothing observable separates "EOF handled" from "server never cancels", so the ordering cannot be made exact from outside mcp-go. The settle goes from 200ms to 500ms, and the comment now states the bound: the error runs one way only, and a server that keeps in-flight calls alive can never be failed by it. The same round's table found that a server running tool calls on the read loop fails the entry gate instead of exercising EOF. The comment now names that too: it means the pin's premise changed, not that EOF cancelled. Controls under -race, same tree: mcp-go 1.1.0 PASS 3/3; 1.1.1 FAIL 3/3; the cancel-at-EOF mutant with read-loop serving FAIL 3/3. Claude-Session: https://claude.ai/code/session_016PXRzXhokr61CLbbu3Txj9 --- internal/mcp/stdio_eof_inflight_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/internal/mcp/stdio_eof_inflight_test.go b/internal/mcp/stdio_eof_inflight_test.go index 4c53eb8f0..f895db339 100644 --- a/internal/mcp/stdio_eof_inflight_test.go +++ b/internal/mcp/stdio_eof_inflight_test.go @@ -34,11 +34,21 @@ import ( // resourceFallback when the server serves it on the read loop itself (as // v1.1.0 does) and therefore cannot read EOF until it returns; in that shape // EOF cannot cancel it, and the tool calls are still held across the EOF. +// +// Two bounds, stated rather than implied. (1) The signal fires inside Read, +// before the server has handled the EOF, and a server that never cancels +// emits nothing to wait for, so the release after it is a timed settle: a +// cancel-at-EOF server whose EOF handling is delayed past eofSettle would +// pass. That error runs one way only; a server that keeps in-flight calls +// alive can never be failed by it. (2) A server that runs tool calls on the +// read loop itself lets only one call in before stdin closes, so the entry +// gate fails with "only 1 of 4 calls reached"; that means this pin's premise +// no longer holds, not that EOF cancelled anything. const ( // eofSettle is how long a release waits after EOF was observed, so a // cancel-at-EOF server has cancelled before the release can win the race. - eofSettle = 200 * time.Millisecond + eofSettle = 500 * time.Millisecond // resourceFallback releases a resource read that blocks the read loop. resourceFallback = time.Second )