Unref open connections in the listener loops to let gc collect when closed #14

Merged
lee.miller merged 2 commits from lee.miller/MiNode:memory into v0.3 2024-10-23 00:36:08 +02:00
3 changed files with 59 additions and 0 deletions

View File

@ -49,6 +49,7 @@ class I2PListener(I2PThread):
destination, 'i2p', self.s, 'i2p', True, destination) destination, 'i2p', self.s, 'i2p', True, destination)
c.start() c.start()
self.state.connections.add(c) self.state.connections.add(c)
c = None
self.new_socket() self.new_socket()
except socket.timeout: except socket.timeout:
pass pass

View File

@ -39,3 +39,4 @@ class Listener(threading.Thread):
c = Connection(*addr[:2], conn, server=True) c = Connection(*addr[:2], conn, server=True)
c.start() c.start()
shared.connections.add(c) shared.connections.add(c)
c = None

View File

@ -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)