From 180402d114973d9a9d938c26591ec300c62f4b95 Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Sat, 17 Feb 2018 10:58:37 +0100 Subject: vpp_papi: reduce memory leaks This changes makes unused VPP objects collectable by garbage collector, allowing running all `make test` tests again instead of python crashing due to running out of memory. Change-Id: I0e271c2b3f195d9d3b64840f9f11144da0fe967d Signed-off-by: Klement Sekera --- src/vpp-api/python/vpp_papi.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'src/vpp-api') diff --git a/src/vpp-api/python/vpp_papi.py b/src/vpp-api/python/vpp_papi.py index 1d92a41a504..25a836956e5 100644 --- a/src/vpp-api/python/vpp_papi.py +++ b/src/vpp-api/python/vpp_papi.py @@ -23,6 +23,7 @@ import struct import json import threading import fnmatch +import weakref import atexit from cffi import FFI import cffi @@ -55,11 +56,12 @@ void vac_set_error_handler(vac_error_callback_t); # Barfs on failure, no need to check success. vpp_api = ffi.dlopen('libvppapiclient.so') -def vpp_atexit(self): +def vpp_atexit(vpp_weakref): """Clean up VPP connection on shutdown.""" - if self.connected: - self.logger.debug('Cleaning up VPP on exit') - self.disconnect() + vpp_instance = vpp_weakref() + if vpp_instance.connected: + vpp_instance.logger.debug('Cleaning up VPP on exit') + vpp_instance.disconnect() vpp_object = None @@ -136,11 +138,7 @@ class VPP(): self.message_queue = queue.Queue() self.read_timeout = read_timeout self.vpp_api = vpp_api - if async_thread: - self.event_thread = threading.Thread( - target=self.thread_msg_handler) - self.event_thread.daemon = True - self.event_thread.start() + self.async_thread = async_thread if not apifiles: # Pick up API definitions from default directory @@ -168,7 +166,7 @@ class VPP(): raise ValueError(1, 'Missing JSON message definitions') # Make sure we allow VPP to clean up the message rings. - atexit.register(vpp_atexit, self) + atexit.register(vpp_atexit, weakref.ref(self)) # Register error handler vpp_api.vac_set_error_handler(vac_error_handler) @@ -664,6 +662,11 @@ class VPP(): self.control_ping_index = vpp_api.vac_get_msg_index( ('control_ping' + '_' + crc[2:]).encode()) self.control_ping_msgdef = self.messages['control_ping'] + if self.async_thread: + self.event_thread = threading.Thread( + target=self.thread_msg_handler) + self.event_thread.daemon = True + self.event_thread.start() return rv def connect(self, name, chroot_prefix=None, async=False, rx_qlen=32): @@ -695,6 +698,7 @@ class VPP(): """Detach from VPP.""" rv = vpp_api.vac_disconnect() self.connected = False + self.message_queue.put("terminate event thread") return rv def msg_handler_sync(self, msg): @@ -712,8 +716,6 @@ class VPP(): if hasattr(r, 'context') and r.context > 0: context = r.context - msgname = type(r).__name__ - if context == 0: # No context -> async notification that we feed to the callback self.message_queue.put_nowait(r) @@ -863,6 +865,8 @@ class VPP(): """ while True: r = self.message_queue.get() + if r == "terminate event thread": + break msgname = type(r).__name__ if self.event_callback: self.event_callback(msgname, r) -- cgit 1.2.3-korg