From 857dd6aa5a88afc81d2a32728a57d2f768d9f65b Mon Sep 17 00:00:00 2001 From: Julien Duponchelle <julien@duponchelle.info> Date: Thu, 17 Nov 2016 21:04:17 +0100 Subject: [PATCH] Fix stop_serving in proactor loop kill all servers Current implementation of the asyncio Proactor event loop has an issue, when you stop a server it's cancel the futures of all other servers. --- asyncio/proactor_events.py | 4 +++- tests/test_proactor_events.py | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/asyncio/proactor_events.py b/asyncio/proactor_events.py index fef32058..f0fca0c8 100644 --- a/asyncio/proactor_events.py +++ b/asyncio/proactor_events.py @@ -544,6 +544,8 @@ def _stop_accept_futures(self): self._accept_futures.clear() def _stop_serving(self, sock): - self._stop_accept_futures() + future = self._accept_futures.pop(sock.fileno(), None) + if future: + future.cancel() self._proactor._stop_serving(sock) sock.close() diff --git a/tests/test_proactor_events.py b/tests/test_proactor_events.py index 4dfc6125..e36ebf26 100644 --- a/tests/test_proactor_events.py +++ b/tests/test_proactor_events.py @@ -584,10 +584,21 @@ def test_create_server_cancel(self): self.assertTrue(self.sock.close.called) def test_stop_serving(self): - sock = mock.Mock() - self.loop._stop_serving(sock) - self.assertTrue(sock.close.called) - self.proactor._stop_serving.assert_called_with(sock) + sock1 = mock.Mock() + future1 = mock.Mock() + sock2 = mock.Mock() + future2 = mock.Mock() + self.loop._accept_futures = { + sock1.fileno(): future1, + sock2.fileno(): future2 + } + + self.loop._stop_serving(sock1) + self.assertTrue(sock1.close.called) + self.assertTrue(future1.cancel.called) + self.proactor._stop_serving.assert_called_with(sock1) + self.assertFalse(sock2.close.called) + self.assertFalse(future2.cancel.called) if __name__ == '__main__':