diff options
author | Klement Sekera <ksekera@cisco.com> | 2018-02-17 10:58:37 +0100 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2018-02-17 20:42:49 +0000 |
commit | 180402d114973d9a9d938c26591ec300c62f4b95 (patch) | |
tree | 99cfa6b4cad9c295f1c41c76f3dab1dd7dc531ae /src/vpp-api/python/vpp_papi.py | |
parent | 54432f8c0ac1f680198afa6047ce74bc4a126f21 (diff) |
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 <ksekera@cisco.com>
Diffstat (limited to 'src/vpp-api/python/vpp_papi.py')
-rw-r--r-- | src/vpp-api/python/vpp_papi.py | 28 |
1 files changed, 16 insertions, 12 deletions
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) |