# coding=utf-8

import logging
import threading
import traceback


class Handler(object):
    """
    Handlers process metrics that are collected by Collectors.
    """
    def __init__(self, config=None):
        """
        Create a new instance of the Handler class
        """
        # Initialize Log
        self.log = logging.getLogger('diamond')
        # Initialize Data
        self.config = config
        # Initialize Lock
        self.lock = threading.Condition(threading.Lock())

    def _process(self, metric):
        """
        Decorator for processing handlers with a lock, catching exceptions
        """
        try:
            try:
                self.log.debug("Running Handler %s locked" % (self))
                self.lock.acquire()
                self.process(metric)
                self.lock.release()
            except Exception:
                    self.log.error(traceback.format_exc())
        finally:
            self.lock.release()
            self.log.debug("Unlocked Handler %s" % (self))

    def process(self, metric):
        """
        Process a metric

        Should be overridden in subclasses
        """
        raise NotImplementedError

    def flush(self):
        """
        Flush metrics

        Optional: Should be overridden in subclasses
        """
        pass

# coding=utf-8

import logging
import threading
import traceback


class Handler(object):
    """
    Handlers process metrics that are collected by Collectors.
    """
    def __init__(self, config=None):
        """
        Create a new instance of the Handler class
        """
        # Initialize Log
        self.log = logging.getLogger('diamond')
        # Initialize Data
        self.config = config
        # Initialize Lock
        self.lock = threading.Lock()

    def _process(self, metric):
        """
        Decorator for processing handlers with a lock, catching exceptions
        """
        try:
            try:
                self.log.debug("Running Handler %s locked" % (self))
                self.lock.acquire()
                self.process(metric)
                self.lock.release()
            except Exception:
                self.log.error(traceback.format_exc())
        finally:
            if self.lock.locked():
                self.lock.release()
            self.log.debug("Unlocked Handler %s" % (self))

    def process(self, metric):
        """
        Process a metric

        Should be overridden in subclasses
        """
        raise NotImplementedError

    def flush(self):
        """
        Flush metrics

        Optional: Should be overridden in subclasses
        """
        pass

Change to using threading.Lock instead of threading.Condition, and check lock state before trying to release it during the finally block
Change to using threading.Lock instead of threading.Condition, and check lock state before trying to release it during the finally block
