@@ -97,26 +97,33 @@ async def test_stdio_client_nonexistent_command():
9797
9898
9999@pytest .mark .anyio
100- async def test_stdio_client_universal_cleanup ():
100+ async def test_stdio_client_cleanup_timeout ():
101101 """
102102 Test that stdio_client completes cleanup within reasonable time
103- even when connected to processes that exit slowly .
103+ even when connected to processes that don't exit cleanly .
104104 """
105105
106- # Use a simple sleep command that's available on all platforms
107- # This simulates a process that takes time to terminate
108- if sys .platform == "win32" :
109- # Windows: use ping with timeout to simulate a running process
110- server_params = StdioServerParameters (
111- command = "ping" ,
112- args = ["127.0.0.1" , "-n" , "10" ], # Ping 10 times, takes ~10 seconds
113- )
114- else :
115- # Unix: use sleep command
116- server_params = StdioServerParameters (
117- command = "sleep" ,
118- args = ["10" ], # Sleep for 10 seconds
119- )
106+ # Use a Python script that ignores SIGTERM and runs forever
107+ # This simulates a stubborn process that won't terminate cleanly
108+ script_content = textwrap .dedent (
109+ """
110+ import signal
111+ import time
112+
113+ # Ignore SIGTERM on Unix
114+ if hasattr(signal, 'SIGTERM'):
115+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
116+
117+ # Just keep running
118+ while True:
119+ time.sleep(0.1)
120+ """
121+ )
122+
123+ server_params = StdioServerParameters (
124+ command = sys .executable ,
125+ args = ["-c" , script_content ],
126+ )
120127
121128 start_time = time .time ()
122129
@@ -143,45 +150,6 @@ async def test_stdio_client_universal_cleanup():
143150 )
144151
145152
146- @pytest .mark .anyio
147- async def test_stdio_client_immediate_completion ():
148- """
149- Test that stdio_client doesn't introduce unnecessary delays
150- when processes exit normally and quickly.
151- """
152-
153- # Use a Python script that prints and exits after a brief moment
154- # This avoids race conditions on fast systems where the process
155- # exits before async tasks are fully initialized
156- script_content = "import time; print('hello'); time.sleep(0.1)"
157-
158- server_params = StdioServerParameters (
159- command = sys .executable ,
160- args = ["-c" , script_content ],
161- )
162-
163- start_time = time .time ()
164-
165- # Use move_on_after which is more reliable for cleanup scenarios
166- with anyio .move_on_after (3.0 ) as cancel_scope :
167- async with stdio_client (server_params ) as (read_stream , write_stream ):
168- pass
169-
170- end_time = time .time ()
171- elapsed = end_time - start_time
172-
173- # Should complete very quickly when process exits normally
174- assert elapsed < 2.0 , (
175- f"stdio_client took { elapsed :.1f} seconds for fast-exiting process, "
176- f"expected < 2.0 seconds. Timeout mechanism may be introducing delays."
177- )
178-
179- # Check if we timed out
180- if cancel_scope .cancelled_caught :
181- pytest .fail (
182- "stdio_client timed out after 3.0 seconds for fast-exiting process. "
183- "This indicates a serious hang in the cleanup mechanism."
184- )
185153
186154
187155@pytest .mark .anyio
0 commit comments