mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-09-28 14:50:14 +03:00
Merge pull request #2669 from arl1984/fix/telnet-proxy-reader-cleanup-2344
Fix telnet console silent-proxy hang on non-ConnectionError exit (#2344)
This commit is contained in:
commit
cd03abb7ed
@ -215,18 +215,32 @@ class AsyncioTelnetServer:
|
|||||||
await self._write_intro(network_writer, echo=self._echo, binary=self._binary, naws=self._naws)
|
await self._write_intro(network_writer, echo=self._echo, binary=self._binary, naws=self._naws)
|
||||||
await connection.connected()
|
await connection.connected()
|
||||||
await self._process(network_reader, network_writer, connection)
|
await self._process(network_reader, network_writer, connection)
|
||||||
except (ConnectionError, OSError):
|
except (ConnectionError, OSError, asyncio.CancelledError):
|
||||||
|
pass
|
||||||
|
except Exception:
|
||||||
|
# Catch any unexpected exception so the cleanup below still runs.
|
||||||
|
# Without the try/finally, an uncaught exception here would leave
|
||||||
|
# _reader_process pinned to a dead reader, and subsequent client
|
||||||
|
# connections would see _get_reader() return None and never
|
||||||
|
# receive node output -- the "silent proxy" hang (issue #2344).
|
||||||
|
log.exception("Unexpected error in telnet proxy; cleaning up client connection...")
|
||||||
|
finally:
|
||||||
async with self._lock:
|
async with self._lock:
|
||||||
network_writer.close()
|
try:
|
||||||
# await network_writer.wait_closed() # this doesn't work in Python 3.6
|
network_writer.close()
|
||||||
if self._reader_process == network_reader:
|
finally:
|
||||||
self._reader_process = None
|
if self._reader_process == network_reader:
|
||||||
# Cancel current read from this reader
|
self._reader_process = None
|
||||||
if self._current_read is not None:
|
# Cancel current read from this reader
|
||||||
self._current_read.cancel()
|
if self._current_read is not None:
|
||||||
|
self._current_read.cancel()
|
||||||
await connection.disconnected()
|
self._current_read = None
|
||||||
del self._connections[network_writer]
|
try:
|
||||||
|
await connection.disconnected()
|
||||||
|
finally:
|
||||||
|
# Use pop() to avoid KeyError if connection was already removed
|
||||||
|
# elsewhere (e.g. by the broadcast loop's timeout handler)
|
||||||
|
self._connections.pop(network_writer, None)
|
||||||
|
|
||||||
async def close(self):
|
async def close(self):
|
||||||
for writer, connection in self._connections.items():
|
for writer, connection in self._connections.items():
|
||||||
@ -318,7 +332,7 @@ class AsyncioTelnetServer:
|
|||||||
except (OSError, ConnectionError, asyncio.TimeoutError) as e:
|
except (OSError, ConnectionError, asyncio.TimeoutError) as e:
|
||||||
log.debug(f"Error sending data to client {client_info}: {e}, closing and removing from connection table.")
|
log.debug(f"Error sending data to client {client_info}: {e}, closing and removing from connection table.")
|
||||||
connection.close()
|
connection.close()
|
||||||
del self._connections[connection_key]
|
self._connections.pop(connection_key, None)
|
||||||
|
|
||||||
async def _read(self, cmd, buffer, location, reader):
|
async def _read(self, cmd, buffer, location, reader):
|
||||||
""" Reads next op from the buffer or reader"""
|
""" Reads next op from the buffer or reader"""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user