@@ -127,7 +127,7 @@ async def stdio_client(server: StdioServerParameters, errlog: TextIO = sys.stder
127127 cwd = server .cwd ,
128128 )
129129
130- async def stdout_reader ():
130+ async def stdout_reader (done_event : anyio . Event ):
131131 assert process .stdout , "Opened process is missing stdout"
132132
133133 try :
@@ -151,6 +151,7 @@ async def stdout_reader():
151151 await read_stream_writer .send (message )
152152 except anyio .ClosedResourceError :
153153 await anyio .lowlevel .checkpoint ()
154+ done_event .set ()
154155
155156 async def stdin_writer ():
156157 assert process .stdin , "Opened process is missing stdin"
@@ -174,21 +175,30 @@ async def stdin_writer():
174175 anyio .create_task_group () as tg ,
175176 process ,
176177 ):
177- tg .start_soon (stdout_reader )
178+ stdout_done_event = anyio .Event ()
179+ tg .start_soon (stdout_reader , stdout_done_event )
178180 tg .start_soon (stdin_writer )
179- # tg.start_soon(monitor_process, tg.cancel_scope)
180181 try :
181182 yield read_stream , write_stream
183+ if stdout_done_event .is_set ():
184+ # The stdout reader exited before the calling code stopped listening
185+ # (e.g. because of process error)
186+ # Give the process a chance to exit if it was the reason for crashing
187+ # so we can get exit code
188+ with anyio .move_on_after (0.1 ) as scope :
189+ await process .wait ()
190+ process_error = f"Process exited with code { process .returncode } ."
191+ if scope .cancelled_caught :
192+ process_error = (
193+ "Stdout reader exited (process did not exit immediately)."
194+ )
182195 finally :
183196 await read_stream .aclose ()
184197 await write_stream .aclose ()
185198 await read_stream_writer .aclose ()
186199 await write_stream_reader .aclose ()
187-
188- if process .returncode is not None and process .returncode != 0 :
189- process_error = f"Process exited with code { process .returncode } ."
190- else :
191- # Clean up process to prevent any dangling orphaned processes
200+ # Clean up process to prevent any dangling orphaned processes
201+ if process .returncode is None :
192202 if sys .platform == "win32" :
193203 await terminate_windows_process (process )
194204 else :
0 commit comments