From 6bbae19d39bf7d7ccc0ec203495eb1eb3e2d096c Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 18 Sep 2018 20:25:31 +0200 Subject: [PATCH] Lock timeout and reset in case a plugin takes too long to initialize or the lock is incorrectly marked as locked in multiprocess context --- platypush/context/__init__.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/platypush/context/__init__.py b/platypush/context/__init__.py index 95945b589..5667293b1 100644 --- a/platypush/context/__init__.py +++ b/platypush/context/__init__.py @@ -2,6 +2,7 @@ import importlib import logging from threading import Lock +from contextlib import contextmanager from ..config import Config @@ -20,6 +21,13 @@ plugins_init_locks = {} # Reference to the main application bus main_bus = None +@contextmanager +def acquire_timeout(lock, timeout): + acquired = lock.acquire(timeout=timeout) + yield acquired + if acquired: + lock.release() + def register_backends(bus=None, global_scope=False, **kwargs): """ Initialize the backend objects based on the configuration and returns a name -> backend_instance map. @@ -98,7 +106,11 @@ def get_plugin(plugin_name, reload=False): logger.warning('No such class in {}: {}'.format(plugin_name, cls_name)) raise RuntimeError(e) - with plugins_init_locks[plugin_name]: + with acquire_timeout(plugins_init_locks[plugin_name], 5) as acquired: + if not acquired: + logger.warning('Lock expired on get_plugin({}), resetting it'.format(plugin_name)) + plugins_init_locks[plugin_name] = Lock() + if plugins.get(plugin_name) and not reload: return plugins[plugin_name] plugins[plugin_name] = plugin_class(**plugin_conf)