@@ -266,6 +266,38 @@ async def serve(rd, wr):
266266 await asyncio .sleep (0 )
267267 self .assertTrue (task .done ())
268268
269+ async def test_close_with_hanging_client (self ):
270+ # Synchronize server cancellation only after the socket connection is
271+ # accepted and this event is set
272+ conn_event = asyncio .Event ()
273+ class Proto (asyncio .Protocol ):
274+ def connection_made (self , transport ):
275+ conn_event .set ()
276+
277+ loop = asyncio .get_running_loop ()
278+ srv = await loop .create_server (Proto , socket_helper .HOSTv4 , 0 )
279+
280+ # Start the server
281+ serve_forever_task = asyncio .create_task (srv .serve_forever ())
282+ await asyncio .sleep (0 )
283+
284+ # Create a connection to server
285+ addr = srv .sockets [0 ].getsockname ()
286+ sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
287+ sock .connect (addr )
288+ self .addCleanup (sock .close )
289+
290+ # Send a CancelledError into the server to emulate a Ctrl+C
291+ # KeyboardInterrupt whilst the server is handling a hanging client
292+ await conn_event .wait ()
293+ serve_forever_task .cancel ()
294+
295+ # Ensure the client is closed within a timeout
296+ async with asyncio .timeout (0.5 ):
297+ await srv .wait_closed ()
298+
299+ self .assertFalse (srv .is_serving ())
300+
269301
270302# Test the various corner cases of Unix server socket removal
271303class UnixServerCleanupTests (unittest .IsolatedAsyncioTestCase ):
0 commit comments