From 105d5bb2fc2246080bc81271762a90d9ce79314a Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Wed, 22 Aug 2018 02:04:16 +0200 Subject: [PATCH] Lock to prevent race conditions where multiple initializations of a plugin can occur --- platypush/context/__init__.py | 14 +++++++++++++- platypush/plugins/gpio/zeroborg/__init__.py | 13 ++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/platypush/context/__init__.py b/platypush/context/__init__.py index 31f6f6d1..7e6e001d 100644 --- a/platypush/context/__init__.py +++ b/platypush/context/__init__.py @@ -1,6 +1,8 @@ import importlib import logging +from threading import Lock + from ..config import Config logger = logging.getLogger(__name__) @@ -11,6 +13,10 @@ backends = {} # Map: plugin_name -> plugin_instance 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 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 returns the registered plugin instance""" global plugins + global plugins_init_locks if plugin_name in plugins and not reload: return plugins[plugin_name] @@ -84,7 +91,12 @@ def get_plugin(plugin_name, reload=False): try: 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 except AttributeError as e: logger.warning('No such class in {}: {}'.format(plugin_name, cls_name)) diff --git a/platypush/plugins/gpio/zeroborg/__init__.py b/platypush/plugins/gpio/zeroborg/__init__.py index dbbf10bd..34180802 100644 --- a/platypush/plugins/gpio/zeroborg/__init__.py +++ b/platypush/plugins/gpio/zeroborg/__init__.py @@ -84,16 +84,11 @@ class GpioZeroborgPlugin(Plugin): self.directions = directions self.auto_mode = False self._direction = None - self.zb = None - if self._init_in_progress.locked(): - raise RuntimeError("ZeroBorg initialization already in progress") - - with self._init_in_progress: - self.zb = ZeroBorg.ZeroBorg() - self.zb.Init() - self.zb.SetCommsFailsafe(True) - self.zb.ResetEpo() + self.zb = ZeroBorg.ZeroBorg() + self.zb.Init() + self.zb.SetCommsFailsafe(True) + self.zb.ResetEpo() def _get_measurement(self, plugin, timeout):