diff options
| author | Tim Burke <tim.burke@gmail.com> | 2019-05-23 12:45:52 -0700 |
|---|---|---|
| committer | Sergey Shepelev <temotor@gmail.com> | 2020-07-31 02:22:48 +0300 |
| commit | 3e5baa8feac8d8f64ae42dad82f290e06604e763 (patch) | |
| tree | cc73f382eb27e33d8e3f5412345af1ca3599cb50 | |
| parent | cc8dc5c296edacd9ff12b058b31a7370727653d3 (diff) | |
| download | eventlet-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.py | 24 | ||||
| -rw-r--r-- | tests/backdoor_test.py | 16 |
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) |
