summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Burke <tim.burke@gmail.com>2019-05-23 12:45:52 -0700
committerSergey Shepelev <temotor@gmail.com>2020-07-31 02:22:48 +0300
commit3e5baa8feac8d8f64ae42dad82f290e06604e763 (patch)
treecc73f382eb27e33d8e3f5412345af1ca3599cb50
parentcc8dc5c296edacd9ff12b058b31a7370727653d3 (diff)
downloadeventlet-3e5baa8feac8d8f64ae42dad82f290e06604e763.tar.gz
backdoor: handle disconnects better
Previously, when a client quickly disconnected (causing a socket.error before the SocketConsole greenlet had a chance to switch), it would break us out of our accept loop, permanently closing the backdoor. Now, it will just break us out of the interactive session, leaving the server ready to accept another backdoor client. Fixes #570
-rw-r--r--eventlet/backdoor.py24
-rw-r--r--tests/backdoor_test.py16
2 files changed, 32 insertions, 8 deletions
diff --git a/eventlet/backdoor.py b/eventlet/backdoor.py
index 9a6797a..f49a969 100644
--- a/eventlet/backdoor.py
+++ b/eventlet/backdoor.py
@@ -32,8 +32,12 @@ class FileProxy(object):
pass
def write(self, data, *a, **kw):
- self.f.write(data, *a, **kw)
- self.f.flush()
+ try:
+ self.f.write(data, *a, **kw)
+ self.f.flush()
+ except socket.error as e:
+ if get_errno(e) != errno.EPIPE:
+ raise
def readline(self, *a):
return self.f.readline(*a).replace('\r\n', '\n')
@@ -99,14 +103,18 @@ def backdoor_server(sock, locals=None):
print("backdoor server listening on %s" % (listening_on,))
try:
- try:
- while True:
+ while True:
+ socketpair = None
+ try:
socketpair = sock.accept()
backdoor(socketpair, locals)
- except socket.error as e:
- # Broken pipe means it was shutdown
- if get_errno(e) != errno.EPIPE:
- raise
+ except socket.error as e:
+ # Broken pipe means it was shutdown
+ if get_errno(e) != errno.EPIPE:
+ raise
+ finally:
+ if socketpair:
+ socketpair[0].close()
finally:
sock.close()
diff --git a/tests/backdoor_test.py b/tests/backdoor_test.py
index d99a4be..03a5692 100644
--- a/tests/backdoor_test.py
+++ b/tests/backdoor_test.py
@@ -57,3 +57,19 @@ class BackdoorTest(tests.LimitedTestCase):
client = socket.socket(socket.AF_UNIX)
client.connect(SOCKET_PATH)
self._run_test_on_client_and_server(client, serv)
+
+ def test_quick_client_disconnect(self):
+ listener = socket.socket()
+ listener.bind(('localhost', 0))
+ listener.listen(50)
+ serv = eventlet.spawn(backdoor.backdoor_server, listener)
+ client = socket.socket()
+ client.connect(('localhost', listener.getsockname()[1]))
+ client.close()
+ # can still reconnect; server is running
+ client = socket.socket()
+ client.connect(('localhost', listener.getsockname()[1]))
+ client.close()
+ serv.kill()
+ # wait for the console to discover that it's dead
+ eventlet.sleep(0.1)