# Buggy code
def Close(self, abort=False):
    """Close the queue.

    Unless the abort parameter is set to true, the underlying socket will remain
    open for _linger_seconds before being destroyed.

    Args:
      abort: Whether the queue is closing due to an error condition, and the
             queue should be close immediately.
    """
    if abort:
        logging.warning("{0:s} Queue aborting. Contents may be lost.".format(self.name))
        self.Empty()
        self._linger_seconds = 0
    else:
        logging.debug(
            "{0:s} Queue closing, will linger for up to {1:d} seconds".format(
                self.name, self._linger_seconds
            )
        )

    if hasattr(self, "terminate_event"):
        self._terminate_event.set()
    self._closed = True


# Traceback (exceptions.AttributeError)
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
File "/usr/lib/python2.7/threading.py", line 763, in run
File "./plaso/engine/zeromq_queue.py", line 651, in _ZeroMQResponder
<type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
File "/usr/lib/python2.7/threading.py", line 763, in run
File "./plaso/engine/zeromq_queue.py", line 752, in _ZeroMQResponder
<type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
File "/usr/lib/python2.7/threading.py", line 763, in run
File "./plaso/engine/zeromq_queue.py", line 752, in _ZeroMQResponder
<type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
/home/travis/build.sh: line 45:  4478 Segmentation fault      (core dumped) coverage run --source=plaso --omit="*_test*,*__init__*,*test_lib*" ./run_tests.py

# Fixed code
def Close(self, abort=False):
    """Closes the queue.

    Args:
      abort (Optional[bool]): whether the Close is the result of an abort
          condition. If True, queue contents may be lost.

    Raises:
      QueueAlreadyClosed: If the queue is not started, or has already been
          closed.
    """
    if self._closed_event.isSet() and not abort:
        raise errors.QueueAlreadyClosed()

    self._closed_event.set()

    if abort:
        logging.warning("{0:s} queue aborting. Contents may be lost.".format(self.name))
        # We can't determine whether a there might be an operation being performed
        # on the socket in a separate method or thread, so we'll signal that any
        # such operation should cease.
        self._terminate_event.set()
        self._linger_seconds = 0

        if self._zmq_thread:
            logging.debug("[{0:s}] Waiting for thread to exit.".format(self.name))
            self._zmq_thread.join(timeout=self.timeout_seconds)
            if self._zmq_thread.isAlive():
                logging.error(
                    ("{0:s} ZMQ responder thread did not exit within timeout").format(
                        self.name
                    )
                )
    else:
        logging.debug(
            "{0:s} queue closing, will linger for up to {1:d} seconds".format(
                self.name, self._linger_seconds
            )
        )