|
1 | 1 | import os |
2 | 2 | import shutil |
| 3 | +import subprocess |
3 | 4 | import sys |
4 | 5 | import tempfile |
5 | 6 | import textwrap |
|
21 | 22 | python: str = shutil.which("python") # type: ignore |
22 | 23 |
|
23 | 24 |
|
| 25 | +class WindowsProcessWrapper: |
| 26 | + """Minimal wrapper for subprocess.Popen to work with anyio-style process interface.""" |
| 27 | + |
| 28 | + def __init__(self, popen): |
| 29 | + self.pid = popen.pid |
| 30 | + self._popen = popen |
| 31 | + |
| 32 | + async def wait(self): |
| 33 | + while self._popen.poll() is None: |
| 34 | + await anyio.sleep(0.1) |
| 35 | + return self._popen.returncode |
| 36 | + |
| 37 | + def terminate(self): |
| 38 | + self._popen.terminate() |
| 39 | + |
| 40 | + def kill(self): |
| 41 | + self._popen.kill() |
| 42 | + |
| 43 | + |
24 | 44 | @pytest.mark.anyio |
25 | 45 | @pytest.mark.skipif(tee is None, reason="could not find tee command") |
26 | 46 | async def test_stdio_context_manager_exiting(): |
@@ -120,7 +140,7 @@ async def test_stdio_client_universal_cleanup(): |
120 | 140 | sys.stderr.flush() |
121 | 141 | """ |
122 | 142 | ) |
123 | | - |
| 143 | + |
124 | 144 | server_params = StdioServerParameters( |
125 | 145 | command=sys.executable, |
126 | 146 | args=["-c", long_running_script], |
@@ -386,7 +406,15 @@ async def test_stdio_client_child_process_cleanup(): |
386 | 406 | print("\nStarting child process termination test...") |
387 | 407 |
|
388 | 408 | # Start the parent process directly with process group |
389 | | - proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True) |
| 409 | + if sys.platform == "win32": |
| 410 | + # Windows: Use subprocess.Popen with CREATE_NEW_PROCESS_GROUP flag |
| 411 | + popen = subprocess.Popen( |
| 412 | + [sys.executable, "-c", parent_script], creationflags=subprocess.CREATE_NEW_PROCESS_GROUP |
| 413 | + ) |
| 414 | + proc = WindowsProcessWrapper(popen) |
| 415 | + else: |
| 416 | + # Unix: Use start_new_session for process group creation |
| 417 | + proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True) |
390 | 418 |
|
391 | 419 | # Wait for processes to start |
392 | 420 | await anyio.sleep(0.5) |
@@ -492,7 +520,15 @@ async def test_stdio_client_nested_process_tree(): |
492 | 520 | ) |
493 | 521 |
|
494 | 522 | # Start parent process directly |
495 | | - proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True) |
| 523 | + if sys.platform == "win32": |
| 524 | + # Windows: Use subprocess.Popen with CREATE_NEW_PROCESS_GROUP flag |
| 525 | + popen = subprocess.Popen( |
| 526 | + [sys.executable, "-c", parent_script], creationflags=subprocess.CREATE_NEW_PROCESS_GROUP |
| 527 | + ) |
| 528 | + proc = WindowsProcessWrapper(popen) |
| 529 | + else: |
| 530 | + # Unix: Use start_new_session for process group creation |
| 531 | + proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True) |
496 | 532 |
|
497 | 533 | # Let all processes start |
498 | 534 | await anyio.sleep(1.0) |
@@ -575,7 +611,15 @@ def handle_term(sig, frame): |
575 | 611 | ) |
576 | 612 |
|
577 | 613 | # Start the parent process |
578 | | - proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True) |
| 614 | + if sys.platform == "win32": |
| 615 | + # Windows: Use subprocess.Popen with CREATE_NEW_PROCESS_GROUP flag |
| 616 | + popen = subprocess.Popen( |
| 617 | + [sys.executable, "-c", parent_script], creationflags=subprocess.CREATE_NEW_PROCESS_GROUP |
| 618 | + ) |
| 619 | + proc = WindowsProcessWrapper(popen) |
| 620 | + else: |
| 621 | + # Unix: Use start_new_session for process group creation |
| 622 | + proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True) |
579 | 623 |
|
580 | 624 | # Let child start writing |
581 | 625 | await anyio.sleep(0.5) |
|
0 commit comments