From 09a00adab939b718e18c8ef544fd2a67b5646687 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Mon, 9 Dec 2019 17:46:44 +0200 Subject: [PATCH] fix: added a plugin::callback level mutex to avoid calling a callback while a previous call is still running --- pwnagotchi/plugins/__init__.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/pwnagotchi/plugins/__init__.py b/pwnagotchi/plugins/__init__.py index 9e7428b6..56aa2d55 100644 --- a/pwnagotchi/plugins/__init__.py +++ b/pwnagotchi/plugins/__init__.py @@ -1,6 +1,7 @@ import os import glob import _thread +import threading import importlib, importlib.util import logging from pwnagotchi.ui import view @@ -8,17 +9,27 @@ from pwnagotchi.ui import view default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default") loaded = {} database = {} +locks = {} + class Plugin: @classmethod def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) - global loaded + global loaded, locks + plugin_name = cls.__module__.split('.')[0] plugin_instance = cls() logging.debug("loaded plugin %s as %s" % (plugin_name, plugin_instance)) loaded[plugin_name] = plugin_instance + for attr_name in plugin_instance.__dir__(): + if attr_name.startswith('on_'): + cb = getattr(plugin_instance, attr_name, None) + if cb is not None and callable(cb): + locks["%s::%s" % (plugin_name, attr_name)] = threading.Lock() + + def toggle_plugin(name, enable=True): """ Load or unload a plugin @@ -48,14 +59,16 @@ def on(event_name, *args, **kwargs): def one(plugin_name, event_name, *args, **kwargs): - global loaded + global loaded, locks + if plugin_name in loaded: plugin = loaded[plugin_name] cb_name = 'on_%s' % event_name callback = getattr(plugin, cb_name, None) if callback is not None and callable(callback): try: - _thread.start_new_thread(callback, (*args, *kwargs)) + with locks["%s::%s" % (plugin_name, cb_name)]: + _thread.start_new_thread(callback, (*args, *kwargs)) except Exception as e: logging.error("error while running %s.%s : %s" % (plugin_name, cb_name, e)) logging.error(e, exc_info=True)