Skip to content

Commit

Permalink
Break Circular References
Browse files Browse the repository at this point in the history
Solve memory leaks by breaking Circular References on writer.close() and connection lost.
  • Loading branch information
fried committed Sep 13, 2020
1 parent c7b90b6 commit 782c677
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 7 deletions.
6 changes: 3 additions & 3 deletions telnetlib3/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def check_negotiation(self, final=False):
encoding = self.encoding(outgoing=True, incoming=True)
if not self.waiter_encoding.done() and result:
self.log.debug('encoding complete: {0!r}'.format(encoding))
self.waiter_encoding.set_result(self)
self.waiter_encoding.set_result(True)

elif (not self.waiter_encoding.done() and
self.writer.remote_option.get(TTYPE) is False):
Expand All @@ -120,13 +120,13 @@ def check_negotiation(self, final=False):
# the distant end would not support it, declaring encoding failed.
self.log.debug('encoding failed after {0:1.2f}s: {1}'
.format(self.duration, encoding))
self.waiter_encoding.set_result(self)
self.waiter_encoding.set_result(True)
return parent

elif not self.waiter_encoding.done() and final:
self.log.debug('encoding failed after {0:1.2f}s: {1}'
.format(self.duration, encoding))
self.waiter_encoding.set_result(self)
self.waiter_encoding.set_result(True)
return parent

return parent and result
Expand Down
12 changes: 8 additions & 4 deletions telnetlib3/server_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ def connection_lost(self, exc):
self._transport.close()
self._waiter_connected.cancel()
if self.shell is None:
self._waiter_closed.set_result(self)
self._waiter_closed.set_result(True)

# break circular refrences.
self._transport = None
self.reader.fn_encoding = None

def connection_made(self, transport):
"""
Expand Down Expand Up @@ -134,7 +138,7 @@ def begin_shell(self, result):
if asyncio.iscoroutine(coro):
fut = self._loop.create_task(coro)
fut.add_done_callback(
lambda fut_obj: self._waiter_closed.set_result(self))
lambda fut_obj: self._waiter_closed.set_result(True))

def data_received(self, data):
"""Process bytes received by transport."""
Expand Down Expand Up @@ -277,11 +281,11 @@ def _check_negotiation_timer(self):
if self.check_negotiation(final=final):
self.log.debug('negotiation complete after {:1.2f}s.'
.format(self.duration))
self._waiter_connected.set_result(self)
self._waiter_connected.set_result(True)
elif final:
self.log.debug('negotiation failed after {:1.2f}s.'
.format(self.duration))
self._waiter_connected.set_result(self)
self._waiter_connected.set_result(True)
else:
# keep re-queuing until complete
self._check_later = self._loop.call_later(
Expand Down
11 changes: 11 additions & 0 deletions telnetlib3/stream_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,17 @@ def __init__(self, transport, protocol, *, client=False, server=False,

# Base protocol methods

def close(self):
super().close()
# break circular refs
self._ext_callback.clear()
self._ext_send_callback.clear()
self._slc_callback.clear()
self._iac_callback.clear()
self.fn_encoding = None
self._protocol = None
self._transport = None

def __repr__(self):
"""Description of stream encoding state."""
info = ['TelnetWriter']
Expand Down

0 comments on commit 782c677

Please sign in to comment.