Skip to content

Commit 03b5266

Browse files
committed
Move process termination to win32.py as well
1 parent c712f04 commit 03b5266

File tree

2 files changed

+30
-15
lines changed

2 files changed

+30
-15
lines changed

src/mcp/client/stdio/__init__.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212

1313
import mcp.types as types
1414

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

1721
# Environment variables to inherit by default
1822
DEFAULT_INHERITED_ENV_VARS = (
@@ -169,21 +173,10 @@ async def stdin_writer():
169173
yield read_stream, write_stream
170174
finally:
171175
# Clean up process to prevent any dangling orphaned processes
172-
try:
176+
if sys.platform == "win32":
177+
terminate_windows_process(process)
178+
else:
173179
process.terminate()
174-
if sys.platform == "win32":
175-
# On Windows, terminating a process with process.terminate() doesn't
176-
# always guarantee immediate process termination.
177-
# So we give it 2s to exit, or we call process.kill()
178-
# which sends a SIGKILL equivalent signal.
179-
try:
180-
with anyio.fail_after(2.0):
181-
await process.wait()
182-
except TimeoutError:
183-
# Force kill if it doesn't terminate
184-
process.kill()
185-
except Exception:
186-
pass
187180

188181

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

src/mcp/client/stdio/win32.py

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

1111
import anyio
12+
from anyio.abc import Process
1213

1314

1415
def get_windows_executable_command(command: str) -> str:
@@ -85,3 +86,24 @@ async def create_windows_process(
8586
[command, *args], env=env, stderr=errlog, cwd=cwd
8687
)
8788
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)