[GH-ISSUE #8555] [Bug] Go verifier can remove its fixture root before MCP ownership completes #6648

Open
opened 2026-11-01 21:12:55 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @morluto on GitHub (Nov 1, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/8555

Originally assigned to: @kaoru0822-kitauji on GitHub.

Area

Other — Go binary verifier

Observed behavior

At revision 245a581818ab13694fa438a06e39898ce03ab206, the Go verifier removes its private fixture root even when either MCP client or transport cleanup fails. Its cleanup loop calls root.close() unconditionally; the client and transport are also constructed before the guarded block.

Reproduction and evidence

On macOS arm64 with Node 24.22.1, a subprocess running the verifier with injected fake compiler, root, and MCP owners reproduced both close calls rejecting while the root-close marker still appeared. Separate simulated constructor failures bypassed cleanup. No real Go compiler or MCP provider was run. The installed MCP SDK's stdio transport source also sends a final SIGKILL and can return before the child emits close; that is a source-derived limitation, not a reproduced late-exit event.

Expected behavior and impact

The verifier should retain ownership of the fixture root until acquired process and transport owners have actually finished, report failures without discarding the primary error, and retain the root when completion cannot be proved. A temporary scratch fix that merely waits for successful SDK close calls is insufficient if those calls return before child exit. Real-provider frequency and impact are NOT_ENOUGH_INFO.

Environment and next checks

Source revision above; Node 24.22.1, macOS arm64; instrumented subprocess with fake owners. Interface: verification script; stage: cleanup and process ownership. A follow-up should use the shared process supervision/completion primitives and cover late exit after final kill, constructor failure, mixed close outcomes, retained-root reporting, and retry where ownership is retained. Real Go and native Windows behavior remain unverified.

Originally created by @morluto on GitHub (Nov 1, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8555 Originally assigned to: @kaoru0822-kitauji on GitHub. ### Area Other — Go binary verifier ### Observed behavior At revision `245a581818ab13694fa438a06e39898ce03ab206`, the Go verifier removes its private fixture root even when either MCP client or transport cleanup fails. Its [cleanup loop](https://github.com/morluto/rea/blob/245a581818ab13694fa438a06e39898ce03ab206/scripts/verify-go-binary.mjs#L197-L216) calls `root.close()` unconditionally; the client and transport are also constructed before the guarded block. ### Reproduction and evidence On macOS arm64 with Node 24.22.1, a subprocess running the verifier with injected fake compiler, root, and MCP owners reproduced both close calls rejecting while the root-close marker still appeared. Separate simulated constructor failures bypassed cleanup. No real Go compiler or MCP provider was run. The installed MCP SDK's stdio transport source also sends a final SIGKILL and can return before the child emits `close`; that is a source-derived limitation, not a reproduced late-exit event. ### Expected behavior and impact The verifier should retain ownership of the fixture root until acquired process and transport owners have actually finished, report failures without discarding the primary error, and retain the root when completion cannot be proved. A temporary scratch fix that merely waits for successful SDK close calls is insufficient if those calls return before child exit. Real-provider frequency and impact are NOT_ENOUGH_INFO. ### Environment and next checks Source revision above; Node 24.22.1, macOS arm64; instrumented subprocess with fake owners. Interface: verification script; stage: cleanup and process ownership. A follow-up should use the shared process supervision/completion primitives and cover late exit after final kill, constructor failure, mixed close outcomes, retained-root reporting, and retry where ownership is retained. Real Go and native Windows behavior remain unverified.
Author
Owner

@morluto commented on GitHub (Nov 1, 2026):

Additional controlled evidence on macOS arm64 with Node 24.22.1: the installed @modelcontextprotocol/client 2.3.1 StdioClientTransport was started with a disposable Node child that stayed open and ignored SIGTERM. After the transport's two grace periods, close() returned after about four seconds, before its child close event; the event arrived shortly afterward. An immediate kill(pid, 0) also succeeded, which does not distinguish a running process from a zombie.

This reproduces the transport completion gap described above. It does not establish that the child was still executing at return, or measure frequency or impact in the Go verifier. No Go compiler or real MCP provider was run.

<!-- gh-comment-id:6560660316 --> @morluto commented on GitHub (Nov 1, 2026): Additional controlled evidence on macOS arm64 with Node 24.22.1: the installed `@modelcontextprotocol/client` 2.3.1 `StdioClientTransport` was started with a disposable Node child that stayed open and ignored SIGTERM. After the transport's two grace periods, `close()` returned after about four seconds, before its child `close` event; the event arrived shortly afterward. An immediate `kill(pid, 0)` also succeeded, which does not distinguish a running process from a zombie. This reproduces the transport completion gap described above. It does not establish that the child was still executing at return, or measure frequency or impact in the Go verifier. No Go compiler or real MCP provider was run.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#6648
No description provided.