@@ -185,29 +185,47 @@ async def stdin_writer():
185185 # 1. Close input stream to server
186186 # 2. Wait for server to exit, or send SIGTERM if it doesn't exit in time
187187 # 3. Send SIGKILL if still not exited
188+ import logging
189+ logger = logging .getLogger ("mcp.stdio_debug" )
190+ logger .info ("Starting cleanup sequence..." )
191+
188192 if process .stdin :
189193 try :
194+ logger .info ("Closing stdin..." )
190195 await process .stdin .aclose ()
191- except Exception :
196+ logger .info ("stdin closed" )
197+ except Exception as e :
192198 # stdin might already be closed, which is fine
199+ logger .info (f"stdin close exception (ignored): { e } " )
193200 pass
194201
195202 try :
196203 # Give the process time to exit gracefully after stdin closes
204+ logger .info ("Waiting for process to exit after stdin closure..." )
197205 with anyio .fail_after (2.0 ):
198206 await process .wait ()
207+ logger .info ("Process exited gracefully" )
199208 except TimeoutError :
200209 # Process didn't exit from stdin closure, use our termination function
201210 # that handles child processes properly
211+ logger .info ("Process didn't exit from stdin closure, terminating..." )
202212 await _terminate_process_with_children (process )
213+ logger .info ("Process terminated" )
203214 except ProcessLookupError :
204215 # Process already exited, which is fine
216+ logger .info ("Process already exited" )
205217 pass
206218
219+ logger .info ("Closing streams..." )
207220 await read_stream .aclose ()
221+ logger .info ("read_stream closed" )
208222 await write_stream .aclose ()
223+ logger .info ("write_stream closed" )
209224 await read_stream_writer .aclose ()
225+ logger .info ("read_stream_writer closed" )
210226 await write_stream_reader .aclose ()
227+ logger .info ("write_stream_reader closed" )
228+ logger .info ("Cleanup complete" )
211229
212230
213231def _get_executable_command (command : str ) -> str :
@@ -265,6 +283,9 @@ async def _terminate_process_with_children(process: Process | FallbackProcess, t
265283 process: The process to terminate
266284 timeout: Time to wait for graceful termination before force killing
267285 """
286+ import logging
287+ logger = logging .getLogger ("mcp.stdio_debug" )
288+ logger .info (f"_terminate_process_with_children called for process on { sys .platform } " )
268289 if sys .platform != "win32" :
269290 # POSIX: Kill entire process group to avoid orphaning children
270291 pid = getattr (process , "pid" , None )
@@ -302,17 +323,23 @@ async def _terminate_process_with_children(process: Process | FallbackProcess, t
302323
303324 # Try graceful termination first
304325 try :
326+ logger .info (f"Calling terminate() on process with PID { pid } " )
305327 process .terminate ()
328+ logger .info ("Waiting for process to exit after terminate()..." )
306329 with anyio .fail_after (timeout ):
307330 await process .wait ()
331+ logger .info ("Process exited after terminate()" )
308332 except TimeoutError :
309333 # Force kill using taskkill for tree termination
310- await anyio .to_thread .run_sync (
334+ logger .info (f"Process didn't exit after terminate(), force killing with taskkill" )
335+ result = await anyio .to_thread .run_sync (
311336 subprocess .run ,
312337 ["taskkill" , "/F" , "/T" , "/PID" , str (pid )],
313338 capture_output = True ,
314339 shell = False ,
315340 check = False ,
316341 )
342+ logger .info (f"taskkill result: returncode={ result .returncode } , stdout={ result .stdout } , stderr={ result .stderr } " )
317343 except ProcessLookupError :
344+ logger .info ("Process already exited (ProcessLookupError)" )
318345 pass
0 commit comments