Skip to content

Commit 5ffc436

Browse files
Fix process termination in stdio client
Github-Issue: #391
1 parent 70115b9 commit 5ffc436

File tree

2 files changed

+8
-32
lines changed

2 files changed

+8
-32
lines changed

src/mcp/client/stdio/__init__.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@
66

77
import anyio
88
import anyio.lowlevel
9-
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
9+
from anyio.streams.memory import (
10+
MemoryObjectReceiveStream,
11+
MemoryObjectSendStream,
12+
)
1013
from anyio.streams.text import TextReceiveStream
1114
from pydantic import BaseModel, Field
1215

1316
import mcp.types as types
1417

15-
from .win32 import (
16-
create_windows_process,
17-
get_windows_executable_command,
18-
terminate_windows_process,
19-
)
18+
from .win32 import create_windows_process, get_windows_executable_command
2019

2120
# Environment variables to inherit by default
2221
DEFAULT_INHERITED_ENV_VARS = (
@@ -173,10 +172,9 @@ async def stdin_writer():
173172
yield read_stream, write_stream
174173
finally:
175174
# Clean up process to prevent any dangling orphaned processes
176-
if sys.platform == "win32":
177-
await terminate_windows_process(process)
178-
else:
179-
process.terminate()
175+
tg.cancel_scope.cancel()
176+
process.terminate()
177+
await process.wait()
180178

181179

182180
def _get_executable_command(command: str) -> str:

src/mcp/client/stdio/win32.py

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from typing import TextIO
1010

1111
import anyio
12-
from anyio.abc import Process
1312

1413

1514
def get_windows_executable_command(command: str) -> str:
@@ -86,24 +85,3 @@ async def create_windows_process(
8685
[command, *args], env=env, stderr=errlog, cwd=cwd
8786
)
8887
return process
89-
90-
91-
async def terminate_windows_process(process: Process):
92-
"""
93-
Terminate a Windows process.
94-
95-
Note: On Windows, terminating a process with process.terminate() doesn't
96-
always guarantee immediate process termination.
97-
So we give it 2s to exit, or we call process.kill()
98-
which sends a SIGKILL equivalent signal.
99-
100-
Args:
101-
process: The process to terminate
102-
"""
103-
try:
104-
process.terminate()
105-
with anyio.fail_after(2.0):
106-
await process.wait()
107-
except TimeoutError:
108-
# Force kill if it doesn't terminate
109-
process.kill()

0 commit comments

Comments
 (0)