Lock to prevent race conditions where multiple initializations of a plugin can occur

This commit is contained in:
Fabio Manganiello 2018-08-22 02:04:16 +02:00
parent e5d67c9393
commit 105d5bb2fc
2 changed files with 17 additions and 10 deletions

View file

@ -1,6 +1,8 @@
import importlib import importlib
import logging import logging
from threading import Lock
from ..config import Config from ..config import Config
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -11,6 +13,10 @@ backends = {}
# Map: plugin_name -> plugin_instance # Map: plugin_name -> plugin_instance
plugins = {} plugins = {}
# Map: plugin_name -> init_lock to make sure that a plugin isn't initialized
# multiple times
plugins_init_locks = {}
# Reference to the main application bus # Reference to the main application bus
main_bus = None main_bus = None
@ -63,6 +69,7 @@ def get_plugin(plugin_name, reload=False):
""" Registers a plugin instance by name if not registered already, or """ Registers a plugin instance by name if not registered already, or
returns the registered plugin instance""" returns the registered plugin instance"""
global plugins global plugins
global plugins_init_locks
if plugin_name in plugins and not reload: if plugin_name in plugins and not reload:
return plugins[plugin_name] return plugins[plugin_name]
@ -84,7 +91,12 @@ def get_plugin(plugin_name, reload=False):
try: try:
plugin_class = getattr(plugin, cls_name) plugin_class = getattr(plugin, cls_name)
plugin = plugin_class(**plugin_conf) if plugin_name not in plugins_init_locks:
plugins_init_locks[plugin_name] = Lock()
with plugins_init_locks[plugin_name]:
plugin = plugin_class(**plugin_conf)
plugins[plugin_name] = plugin plugins[plugin_name] = plugin
except AttributeError as e: except AttributeError as e:
logger.warning('No such class in {}: {}'.format(plugin_name, cls_name)) logger.warning('No such class in {}: {}'.format(plugin_name, cls_name))

View file

@ -84,16 +84,11 @@ class GpioZeroborgPlugin(Plugin):
self.directions = directions self.directions = directions
self.auto_mode = False self.auto_mode = False
self._direction = None self._direction = None
self.zb = None
if self._init_in_progress.locked(): self.zb = ZeroBorg.ZeroBorg()
raise RuntimeError("ZeroBorg initialization already in progress") self.zb.Init()
self.zb.SetCommsFailsafe(True)
with self._init_in_progress: self.zb.ResetEpo()
self.zb = ZeroBorg.ZeroBorg()
self.zb.Init()
self.zb.SetCommsFailsafe(True)
self.zb.ResetEpo()
def _get_measurement(self, plugin, timeout): def _get_measurement(self, plugin, timeout):