GH-79033: Fix asyncio.Server.wait_closed() (#98582)

It was a no-op when used as recommended (after close()).

I had to debug one test (test__sock_sendfile_native_failure) --
the cleanup sequence for the test fixture was botched.

Hopefully that's not a portend of problems in user code --
this has never worked so people may well be doing this wrong. :-(

Co-authored-by: kumar aditya
This commit is contained in:
Guido van Rossum 2022-11-24 07:32:58 -08:00 committed by GitHub
parent 8dbe08eb7c
commit 5d09d11aa0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 2 deletions

View file

@ -377,7 +377,7 @@ class Server(events.AbstractServer):
self._serving_forever_fut = None
async def wait_closed(self):
if self._sockets is None or self._waiters is None:
if self._waiters is None or self._active_count == 0:
return
waiter = self._loop.create_future()
self._waiters.append(waiter)

View file

@ -2052,11 +2052,11 @@ class BaseLoopSockSendfileTests(test_utils.TestCase):
def cleanup():
server.close()
self.run_loop(server.wait_closed())
sock.close()
if proto.transport is not None:
proto.transport.close()
self.run_loop(proto.wait_closed())
self.run_loop(server.wait_closed())
self.addCleanup(cleanup)

View file

@ -120,6 +120,33 @@ class SelectorStartServerTests(BaseStartServer, unittest.TestCase):
self.loop.run_until_complete(srv.serve_forever())
class TestServer2(unittest.IsolatedAsyncioTestCase):
async def test_wait_closed(self):
async def serve(*args):
pass
srv = await asyncio.start_server(serve, socket_helper.HOSTv4, 0)
# active count = 0
task1 = asyncio.create_task(srv.wait_closed())
await asyncio.sleep(0)
self.assertTrue(task1.done())
# active count != 0
srv._attach()
task2 = asyncio.create_task(srv.wait_closed())
await asyncio.sleep(0)
self.assertFalse(task2.done())
srv.close()
await asyncio.sleep(0)
self.assertFalse(task2.done())
srv._detach()
await task2
@unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only')
class ProactorStartServerTests(BaseStartServer, unittest.TestCase):

View file

@ -0,0 +1 @@
Fix :func:`asyncio.Server.wait_closed` to actually do what the docs promise -- wait for all existing connections to complete, after closing the server.