@@ -43,9 +43,21 @@ proc newMcpSocketClient(port: Port): Future[McpSocketClient] {.async.} =
4343 let addresses = resolveTAddress (" localhost" , port)
4444 McpSocketClient (transport: await connect (addresses[0 ]))
4545
46- proc close (client: McpSocketClient ): Future [void ] {.async .} =
46+ proc close (client: McpSocketClient ) =
47+ # XXX `closeWait` (close + join) never returns on Windows CI. Wait for the
48+ # join with timer-driven polling instead of blocking on it: timers do not
49+ # involve IOCP, so if these ticks happen the event loop is alive and only
50+ # this transport's completion is missing; if the line below never prints,
51+ # `poll()` itself is wedged. Either way CI reports instead of hanging.
4752 if not client.transport.isNil:
48- await client.transport.closeWait ()
53+ client.transport.close ()
54+ echo " [tmcp] close() returned, closed=" , client.transport.closed ()
55+ let joined = noCancel (client.transport.join ())
56+ var waited = 0
57+ while not joined.finished () and waited < 100 :
58+ waitFor sleepAsync (100 .milliseconds)
59+ inc waited
60+ echo " [tmcp] join finished=" , joined.finished (), " after " , waited * 100 , " ms"
4961
5062proc readResponseLine (client: McpSocketClient ): Future [string ] {.async .} =
5163 while true :
@@ -110,15 +122,11 @@ suite "MCP routes":
110122 port: getNextFreePort (),
111123 )
112124 rpcLs = main (rpcCmdParams)
113-
114- rpcLs.notify = proc (name: string , params: JsonNode ) {.gcsafe , raises : [].} =
115- discard
116-
117- let rpcClient = waitFor newMcpSocketClient (rpcCmdParams.port)
125+ rpcClient = waitFor newMcpSocketClient (rpcCmdParams.port)
118126
119127 defer :
120128 echo " [tmcp] closing rpc client"
121- waitFor rpcClient.close ()
129+ rpcClient.close ()
122130 echo " [tmcp] rpc client closed; calling onExit"
123131 waitFor rpcLs.onExit ()
124132 setCurrentDir (savedDir)
0 commit comments