Watchdog timer

Sometimes it can be really important to see if something is called in a periodic manner. You could think about a webservice in a quite messy environment. One of its clients dies sometimes without any error, and the only way to fix the problem is to reset the connection.

This is a situation when a watchdog timer, or a dead men’s switch becomes handy.

To show the functionality here is a small example.

import signal
from functools import wraps

def timeout_handler(signum, frame):
    raise TimeoutError("worker stopped doing things.")

signal.signal(signal.SIGALRM, timeout_handler)

    
def resets_watchdog(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        signal.alarm(60*2)
        return func(*args, **kwargs)
    return wrapper


class LazyWorker:
    @resets_watchdog
    def doing_things(self):
        pass

Like in my previous post we make use of signal.SIGALRM. The class LazyWorker has a function doing_things(), which is decorated by the resets_watchdog(). Everytime the wrapper is called, the alarm is (re)set to 120 seconds. This means, if there is no interaction on the function doing_things() for two minutes, the signal-handler is called and raises the TimeoutError.

This is everything you need to have a working watchdog inside the service.