X-Git-Url: https://git.ralfj.de/saartuer.git/blobdiff_plain/7d24ee0e013ba6d9442a4822f44818e10772e3d6..8fa0d3c2b93ded551a61f48e2c8701e5f2370b76:/libtuer.py diff --git a/libtuer.py b/libtuer.py index 308179e..f1e8d54 100644 --- a/libtuer.py +++ b/libtuer.py @@ -5,11 +5,13 @@ import email.mime.text, email.utils # Logging configuration syslogLevel = logging.INFO mailLevel = logging.CRITICAL # must be "larger" than syslog level! -mailAddress = ['post+tuer'+'@'+'ralfj.de', 'vorstand@lists.hacksaar.de'] +from config import mailAddress +printLevel = logging.DEBUG # Mail logging handler def sendeMail(subject, text, receivers, sender='sphinx@hacksaar.de', replyTo=None): - if not isinstance(type(receivers), list): receivers = [receivers] + assert isinstance(receivers, list) + if not len(receivers): return # nothing to do # construct content msg = email.mime.text.MIMEText(text.encode('UTF-8'), 'plain', 'UTF-8') msg['Subject'] = subject @@ -27,18 +29,20 @@ def sendeMail(subject, text, receivers, sender='sphinx@hacksaar.de', replyTo=Non class Logger: def __init__ (self): self.syslog = logging.getLogger("tuerd") - self.syslog.setLevel(syslogLevel) + self.syslog.setLevel(logging.DEBUG) self.syslog.addHandler(logging.handlers.SysLogHandler(address = '/dev/log', facility = logging.handlers.SysLogHandler.LOG_LOCAL0)) def _log (self, lvl, what): thestr = "%s[%d]: %s" % ("tuerd", os.getpid(), what) # console log - print(thestr) + if lvl >= printLevel: + print(thestr) # syslog - self.syslog.log(lvl, thestr) + if lvl >= syslogLevel: + self.syslog.log(lvl, thestr) # mail log - if lvl >= mailLevel: + if lvl >= mailLevel and mailAddress is not None: sendeMail('Kritischer Türfehler', what, mailAddress) def debug(self, what): @@ -54,16 +58,26 @@ class Logger: logger = Logger() +# run a Python command asynchronously +def fire_and_forget(f): + def _fire_and_forget(): + try: + f() + except Exception: + logger.critical("fire_and_forget: Got exception out of callback:\n%s" % traceback.format_exc()) + t = threading.Thread(target=_fire_and_forget) + t.start() + # run a command asynchronously and log the return value if not 0 # prefix must be a string identifying the code position where the call came from -def fire_and_forget (cmd, log, prefix): - def _fire_and_forget (): +def fire_and_forget_cmd (cmd, log_prefix): + logger.debug("Firing and forgetting command from %s: %s" % (log_prefix,str(cmd))) + def _fire_and_forget_cmd (): with open("/dev/null", "w") as fnull: retcode = subprocess.call(cmd, stdout=fnull, stderr=fnull) if retcode is not 0: - logger.error("%sReturn code %d at command: %s" % (prefix,retcode,str(cmd))) - t = threading.Thread(target=_fire_and_forget) - t.start() + logger.error("%sReturn code %d at command: %s" % (log_prefix,retcode,str(cmd))) + fire_and_forget(_fire_and_forget_cmd) # Threaded callback class class ThreadFunction(): @@ -85,8 +99,7 @@ class ThreadFunction(): try: self._f(*data) except Exception as e: - logger.critical("ThreadFunction: Got exception out of handler thread %s: %s" % (self.name, str(e))) - logger.debug(traceback.format_exc()) + logger.critical("ThreadFunction: Got exception out of handler thread %s:\n%s" % (self.name, traceback.format_exc())) elif cmd == ThreadFunction._TERM: assert data is None break @@ -97,6 +110,13 @@ class ThreadFunction(): self._q.put((ThreadFunction._CALL, arg)) def stop(self): + # empty the queue + try: + while True: + self._q.get_nowait() + except queue.Empty: + pass + # now wait till the job-in-progress is done self._q.put((ThreadFunction._TERM, None)) self._t.join() @@ -117,8 +137,7 @@ class ThreadRepeater(): try: self._f() except Exception as e: - logger.critical("ThreadRepeater: Got exception out of handler thread %s: %s" % (self.name, str(e))) - logger.debug(traceback.format_exc()) + logger.critical("ThreadRepeater: Got exception out of handler thread %s:\n%s" % (self.name, traceback.format_exc())) time.sleep(self._sleep_time) def stop(self):