Skip to content

Commit

Permalink
GH-79033: Fix asyncio.Server.wait_closed() (#98582)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gvanrossum authored Nov 24, 2022
1 parent 8dbe08e commit 5d09d11
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Lib/asyncio/base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ async def serve_forever(self):
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)
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_asyncio/test_base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -2052,11 +2052,11 @@ def prepare(self):

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)

Expand Down
27 changes: 27 additions & 0 deletions Lib/test/test_asyncio/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,33 @@ async def main(srv):
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):

Expand Down
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit 5d09d11

Please sign in to comment.