From 02f4a4709fee12fa21a6f8bcd89b00a550b6e7d1 Mon Sep 17 00:00:00 2001 From: Ben Jones Date: Tue, 1 Dec 2015 22:53:48 +1300 Subject: [PATCH] Adding timeout to core mqttwarn processor to stop rogue plugins hanging everything --- mqttwarn.py | 25 ++++++++++++++++++++++++- services/xbmc.py | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/mqttwarn.py b/mqttwarn.py index 2ab3560c..97938398 100755 --- a/mqttwarn.py +++ b/mqttwarn.py @@ -671,6 +671,28 @@ def xform(function, orig_value, transform_data): res = res.replace("\\n", "\n") return res +# http://code.activestate.com/recipes/473878-timeout-function-using-threading/ +def timeout(func, args=(), kwargs={}, timeout_secs=10, default=False): + import threading + class InterruptableThread(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + self.result = None + + def run(self): + try: + self.result = func(*args, **kwargs) + except: + self.result = default + + it = InterruptableThread() + it.start() + it.join(timeout_secs) + if it.isAlive(): + return default + else: + return it.result + def processor(): """ Queue runner. Pull a job from the queue, find the module in charge @@ -754,8 +776,9 @@ def processor(): st = Struct(**item) notified = False try: + # fire the plugin in a separate thread and kill it if it doesn't return in 10s module = service_plugins[service]['module'] - notified = module.plugin(srv, st) + notified = timeout(module.plugin, (srv, st)) except Exception, e: logging.error("Cannot invoke service for `%s': %s" % (service, str(e))) diff --git a/services/xbmc.py b/services/xbmc.py index f3f46c95..3e5cddb6 100644 --- a/services/xbmc.py +++ b/services/xbmc.py @@ -51,7 +51,7 @@ def plugin(srv, item): base64string = base64.encodestring ('%s:%s' % (xbmcusername, xbmcpassword))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) - response = urllib2.urlopen(req, timeout = 1) + response = urllib2.urlopen(req, timeout = 2) srv.logging.debug("Successfully sent XBMC notification") except urllib2.URLError, e: srv.logging.error("URLError: %s" % (str(e)))