From 9105c4677c8d51bf8b4a19b9d4f428cf17ca5292 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Mon, 12 Aug 2019 15:46:05 -0400 Subject: [PATCH] bt2: py_plugin.py: cache `_PluginInfo` objects This patch makes _try_load_plugin_module() cache the `_PluginInfo` objects it creates. The cache, `_plugin_infos`, maps a Python plugin absolute path to a `_PluginInfo` object. This avoids loading the Python module twice, which can create problems, for example destroying component classes earlier than expected when the new module replaces the old one in `sys.modules`. Signed-off-by: Philippe Proulx Change-Id: I55397a1d5e65de1f6495dccc23e1134bd1127631 Reviewed-on: https://review.lttng.org/c/babeltrace/+/1887 Tested-by: jenkins --- src/bindings/python/bt2/bt2/py_plugin.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/bindings/python/bt2/bt2/py_plugin.py b/src/bindings/python/bt2/bt2/py_plugin.py index 9d692f2d..f1142766 100644 --- a/src/bindings/python/bt2/bt2/py_plugin.py +++ b/src/bindings/python/bt2/bt2/py_plugin.py @@ -22,6 +22,11 @@ from bt2 import utils from bt2 import component as bt2_component +import sys + + +# Python plugin path to `_PluginInfo` (cache) +_plugin_infos = {} def plugin_component_class(component_class): @@ -35,8 +40,6 @@ def plugin_component_class(component_class): def register_plugin( module_name, name, description=None, author=None, license=None, version=None ): - import sys - if module_name not in sys.modules: raise RuntimeError( "cannot find module '{}' in loaded modules".format(module_name) @@ -102,6 +105,10 @@ class _PluginInfo: # called by the BT plugin system def _try_load_plugin_module(path): + if path in _plugin_infos: + # do not load module and create plugin info twice for this path + return _plugin_infos[path] + import importlib.machinery import inspect import hashlib @@ -115,7 +122,7 @@ def _try_load_plugin_module(path): h = hashlib.sha256() h.update(path.encode()) module_name = 'bt_plugin_{}'.format(h.hexdigest()) - + assert module_name not in sys.modules # try loading the module: any raised exception is catched by the caller mod = importlib.machinery.SourceFileLoader(module_name, path).load_module() @@ -137,4 +144,5 @@ def _try_load_plugin_module(path): comp_class_entries = inspect.getmembers(mod, is_user_comp_class) plugin_info.comp_class_addrs = [entry[1].addr for entry in comp_class_entries] + _plugin_infos[path] = plugin_info return plugin_info -- 2.34.1