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__':