File tree Expand file tree Collapse file tree 2 files changed +36
-4
lines changed
Expand file tree Collapse file tree 2 files changed +36
-4
lines changed Original file line number Diff line number Diff line change @@ -205,10 +205,13 @@ async def stdin_writer():
205205 except ProcessLookupError : # pragma: no cover
206206 # Process already exited, which is fine
207207 pass
208- await read_stream .aclose ()
209- await write_stream .aclose ()
210- await read_stream_writer .aclose ()
211- await write_stream_reader .aclose ()
208+ # Stop background stream tasks before closing the memory streams they use.
209+ tg .cancel_scope .cancel ()
210+
211+ await read_stream .aclose ()
212+ await write_stream .aclose ()
213+ await read_stream_writer .aclose ()
214+ await write_stream_reader .aclose ()
212215
213216
214217def _get_executable_command (command : str ) -> str :
Original file line number Diff line number Diff line change @@ -155,6 +155,35 @@ async def test_stdio_client_universal_cleanup():
155155 )
156156
157157
158+ @pytest .mark .anyio
159+ async def test_stdio_client_cleanup_cancels_backpressured_stdout_reader ():
160+ """Regression test for issue #1960.
161+
162+ Exiting the client without consuming the read stream leaves stdout_reader
163+ blocked on a zero-buffer send. Cleanup must cancel the task before closing
164+ its memory stream.
165+ """
166+ script_content = textwrap .dedent (
167+ """
168+ import sys
169+ import time
170+
171+ sys.stdout.write('{"jsonrpc":"2.0","id":1,"result":{}}\\ n')
172+ sys.stdout.flush()
173+ time.sleep(2.0)
174+ """
175+ )
176+
177+ server_params = StdioServerParameters (
178+ command = sys .executable ,
179+ args = ["-c" , script_content ],
180+ )
181+
182+ with anyio .fail_after (5.0 ):
183+ async with stdio_client (server_params ) as (_ , _ ):
184+ await anyio .sleep (0.2 )
185+
186+
158187@pytest .mark .anyio
159188@pytest .mark .skipif (sys .platform == "win32" , reason = "Windows signal handling is different" )
160189async def test_stdio_client_sigint_only_process (): # pragma: lax no cover
You can’t perform that action at this time.
0 commit comments