Skip to content

Commit 8a62457

Browse files
test
1 parent 79c1980 commit 8a62457

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

src/mcp/os/win32/utilities.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ async def create_windows_process(
184184
Returns:
185185
Process | FallbackProcess: Async-compatible subprocess with stdin and stdout streams
186186
"""
187+
# Log event loop information for debugging CI behavior
188+
try:
189+
import asyncio
190+
loop = asyncio.get_running_loop()
191+
logger.info(f"Windows process creation - Event loop: {loop.__class__.__name__} from {loop.__class__.__module__}")
192+
except Exception:
193+
pass # Don't fail if we can't get loop info
194+
187195
job = _create_job_object()
188196
process = None
189197

@@ -199,11 +207,15 @@ async def create_windows_process(
199207
stderr=errlog,
200208
cwd=cwd,
201209
)
202-
except NotImplementedError:
210+
except NotImplementedError as e:
203211
# If Windows doesn't support async subprocess creation, use fallback
212+
logger.warning(f"anyio.open_process raised NotImplementedError: {e}")
213+
logger.warning("Using FallbackProcess (likely SelectorEventLoop on Windows)")
204214
process = await _create_windows_fallback_process(command, args, env, errlog, cwd)
205-
except Exception:
215+
except Exception as e:
206216
# Try again without creation flags
217+
logger.info(f"anyio.open_process failed with {type(e).__name__}: {e}")
218+
logger.info("Retrying without creation flags")
207219
process = await anyio.open_process(
208220
[command, *args],
209221
env=env,
@@ -212,6 +224,11 @@ async def create_windows_process(
212224
)
213225

214226
_maybe_assign_process_to_job(process, job)
227+
228+
# Log which type of process was created
229+
process_type = type(process).__name__
230+
logger.info(f"Created process type: {process_type} (pid: {process.pid})")
231+
215232
return process
216233

217234

tests/issues/test_1027_win_unreachable_cleanup.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
These tests verify the fix continues to work correctly across all platforms.
99
"""
1010

11+
import platform
12+
1113
import asyncio
1214
import sys
1315
import tempfile
@@ -21,6 +23,45 @@
2123
from mcp.client.stdio import _create_platform_compatible_process, stdio_client
2224

2325

26+
def _get_event_loop_info():
27+
"""Get information about the current event loop for debugging."""
28+
try:
29+
loop = asyncio.get_running_loop()
30+
return {
31+
"class": loop.__class__.__name__,
32+
"module": loop.__class__.__module__,
33+
"is_proactor": "Proactor" in loop.__class__.__name__,
34+
"is_selector": "Selector" in loop.__class__.__name__,
35+
}
36+
except RuntimeError:
37+
return {"error": "No running event loop"}
38+
39+
40+
@pytest.mark.anyio
41+
@pytest.mark.skipif(sys.platform != "win32", reason="Windows-specific event loop detection")
42+
async def test_windows_event_loop_detection():
43+
"""Test to detect which event loop is being used on Windows CI."""
44+
loop_info = _get_event_loop_info()
45+
46+
# Print diagnostic info that will appear in CI logs
47+
print(f"\n{'='*60}")
48+
print("WINDOWS CI EVENT LOOP DIAGNOSTICS")
49+
print(f"{'='*60}")
50+
print(f"Python Version: {sys.version}")
51+
print(f"Platform: {platform.platform()}")
52+
print(f"Event Loop Class: {loop_info.get('class', 'Unknown')}")
53+
print(f"Event Loop Module: {loop_info.get('module', 'Unknown')}")
54+
print(f"Is ProactorEventLoop: {loop_info.get('is_proactor', False)}")
55+
print(f"Is SelectorEventLoop: {loop_info.get('is_selector', False)}")
56+
print(f"{'='*60}")
57+
print("ProactorEventLoop = Supports subprocesses (default since Python 3.8)")
58+
print("SelectorEventLoop = Does NOT support subprocesses (uses FallbackProcess)")
59+
print(f"{'='*60}\n")
60+
61+
# Intentionally fail to ensure output appears in CI logs
62+
pytest.fail("DIAGNOSTIC TEST - Intentionally failing to show event loop info in CI")
63+
64+
2465
@pytest.mark.anyio
2566
async def test_lifespan_cleanup_executed():
2667
"""
@@ -195,9 +236,19 @@ def echo(text: str) -> str:
195236
try:
196237
# This test manually manages the process to verify stdin-based shutdown
197238
# Start the server process
239+
if sys.platform == "win32":
240+
# Force output to stderr which is captured even with xdist
241+
import sys as sys_module
242+
print(f"\n[WINDOWS DIAGNOSTICS] Event loop: {_get_event_loop_info()}", file=sys_module.stderr)
243+
print(f"[WINDOWS DIAGNOSTICS] About to create process...", file=sys_module.stderr)
244+
198245
process = await _create_platform_compatible_process(
199246
command=sys.executable, args=[server_script], env=None, errlog=sys.stderr, cwd=None
200247
)
248+
249+
if sys.platform == "win32":
250+
print(f"[WINDOWS DIAGNOSTICS] Created process type: {type(process).__name__}", file=sys_module.stderr)
251+
print(f"[WINDOWS DIAGNOSTICS] Has returncode: {hasattr(process, 'returncode')}", file=sys_module.stderr)
201252

202253
# Wait for server to start
203254
await asyncio.sleep(1.0) # Give more time on Windows

0 commit comments

Comments
 (0)