bt2: py_plugin.py: cache `_PluginInfo` objects
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Mon, 12 Aug 2019 19:46:05 +0000 (15:46 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 4 Sep 2019 15:58:21 +0000 (11:58 -0400)
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 <eeppeliteloop@gmail.com>
Change-Id: I55397a1d5e65de1f6495dccc23e1134bd1127631
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1887
Tested-by: jenkins <jenkins@lttng.org>
src/bindings/python/bt2/bt2/py_plugin.py

index 9d692f2d32b03579f2dc6cda3ed330fb9050c792..f1142766e3230152ef08acf458ba3069b58ebac7 100644 (file)
 
 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
This page took 0.026169 seconds and 4 git commands to generate.