From dcaee3febfff4d1d21ec6d4344933b20dba233a4 Mon Sep 17 00:00:00 2001 From: Lee Miller Date: Tue, 24 Sep 2024 15:22:39 +0300 Subject: [PATCH 1/2] Add a test for the closed connection remaining in memory --- minode/tests/test_memory.py | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 minode/tests/test_memory.py diff --git a/minode/tests/test_memory.py b/minode/tests/test_memory.py new file mode 100644 index 0000000..dae2377 --- /dev/null +++ b/minode/tests/test_memory.py @@ -0,0 +1,57 @@ +"""Tests for memory usage""" + +import gc +import time + +from minode import shared + +from .test_network import TestProcessProto, run_listener + + +class TestListener(TestProcessProto): + """A separate test case for Listener with a process with --trusted-peer""" + _process_cmd = ['minode', '--trusted-peer', '127.0.0.1'] + + def setUp(self): + shared.shutting_down = False + + @classmethod + def tearDownClass(cls): + super().tearDownClass() + shared.shutting_down = False + + def test_listener(self): + """Start Listener and disconnect a client""" + with run_listener() as listener: + if not listener: + self.fail('Failed to start listener') + + shared.connection_limit = 2 + connected = False + started = time.time() + while not connected: + time.sleep(0.2) + if time.time() - started > 90: + self.fail('Failed to establish the connection') + for c in shared.connections: + if c.status == 'fully_established': + connected = True + + if not self._stop_process(10): + self.fail('Failed to stop the client process') + + for c in shared.connections.copy(): + if not c.is_alive() or c.status == 'disconnected': + shared.connections.remove(c) + c = None + break + else: + self.fail('The connection is alive') + + gc.collect() + for obj in gc.get_objects(): + if ( + isinstance(obj, shared.connection) + and obj not in shared.connections + ): + self.fail('Connection %s remains in memory' % obj) -- 2.45.1 From 9bb3038547dbd57f748288ca44b4427a24c1d019 Mon Sep 17 00:00:00 2001 From: Lee Miller Date: Sun, 25 Aug 2024 15:15:14 +0300 Subject: [PATCH 2/2] Unref open connections in the listener loops to let gc collect when closed --- minode/i2p/listener.py | 1 + minode/listener.py | 1 + 2 files changed, 2 insertions(+) diff --git a/minode/i2p/listener.py b/minode/i2p/listener.py index 9b3d058..f63de06 100644 --- a/minode/i2p/listener.py +++ b/minode/i2p/listener.py @@ -49,6 +49,7 @@ class I2PListener(I2PThread): destination, 'i2p', self.s, 'i2p', True, destination) c.start() self.state.connections.add(c) + c = None self.new_socket() except socket.timeout: pass diff --git a/minode/listener.py b/minode/listener.py index bec5365..815c02d 100644 --- a/minode/listener.py +++ b/minode/listener.py @@ -39,3 +39,4 @@ class Listener(threading.Thread): c = Connection(*addr[:2], conn, server=True) c.start() shared.connections.add(c) + c = None -- 2.45.1