Skip to content

Commit bdc48e9

Browse files
authored
Fix stdio client shutdown bugs and rebuild the stdio test suite (#2773)
1 parent 19fe9fa commit bdc48e9

18 files changed

Lines changed: 2645 additions & 1130 deletions

File tree

docs/migration.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,46 @@ The `headers`, `timeout`, `sse_read_timeout`, and `auth` parameters have been re
105105

106106
Note: `sse_client` retains its `headers`, `timeout`, `sse_read_timeout`, and `auth` parameters — only the streamable HTTP transport changed.
107107

108+
### `terminate_windows_process` removed
109+
110+
The deprecated `mcp.os.win32.utilities.terminate_windows_process` function has been
111+
removed. Process termination is handled internally by the `stdio_client` context
112+
manager; there is no replacement API. The Windows tree-termination helper
113+
`terminate_windows_process_tree` no longer accepts a `timeout_seconds` argument —
114+
the value was never used (Job Object termination is immediate).
115+
116+
### `stdio_client` no longer kills children of a gracefully-exited server on POSIX
117+
118+
When a server exits on its own after `stdio_client` closes its stdin, background
119+
child processes the server leaves behind are no longer killed on POSIX — their
120+
lifetime is the server's business. The old behavior was a side effect of a shutdown
121+
wait gated on the stdio pipes closing rather than on process exit: a child holding
122+
an inherited pipe made a well-behaved server look hung, so its whole process tree
123+
was killed. (That gating is an asyncio behavior specific to Python 3.11+ — on
124+
Python 3.10 and the trio backend the old wait already resolved on process exit, so
125+
the spurious kill never fired there.) A server that does not exit within the grace
126+
period is still terminated
127+
along with its entire process group. On Windows, children stay in the server's Job
128+
Object and are still killed at shutdown — now deterministically when the job handle
129+
is closed, rather than whenever the handle happened to be garbage-collected.
130+
131+
If you relied on `stdio_client` killing everything the server spawned, make the
132+
server terminate its own children on shutdown (its stdin reaching EOF is the
133+
shutdown signal), or clean up the process tree from the host application after
134+
`stdio_client` exits.
135+
136+
Two related shutdown refinements: `stdio_client` now closes its end of the pipes
137+
deterministically at shutdown, so a surviving child that keeps writing to an
138+
inherited stdout receives `EPIPE`/`SIGPIPE` once the client is gone (previously the
139+
pipe lingered until garbage collection); and a failed write to a server that is
140+
still running now surfaces as a closed connection (`CONNECTION_CLOSED`) on the read
141+
side instead of leaving requests waiting indefinitely.
142+
143+
`terminate_posix_process_tree` now requires the process to lead its own process
144+
group (spawned with `start_new_session=True`); the `getpgid()` lookup and the
145+
per-process terminate/kill fallback are gone. The win32 utilities logger is now
146+
named `mcp.os.win32.utilities` (was `client.stdio.win32`).
147+
108148
### Removed type aliases and classes
109149

110150
The following deprecated type aliases and classes have been removed from `mcp.types`:

0 commit comments

Comments
 (0)