# Buggy code
def _Main(self):
    """The main loop."""
    self._parser_mediator = parsers_mediator.ParserMediator(
        None,
        self._knowledge_base,
        preferred_year=self._preferred_year,
        temporary_directory=self._temporary_directory,
    )

    if self._filter_object:
        self._parser_mediator.SetFilterObject(self._filter_object)

    if self._mount_path:
        self._parser_mediator.SetMountPath(self._mount_path)

    if self._text_prepend:
        self._parser_mediator.SetTextPrepend(self._text_prepend)

    # We need a resolver context per process to prevent multi processing
    # issues with file objects stored in images.
    resolver_context = context.Context()

    # We need to initialize the parser and hasher objects after the process
    # has forked otherwise on Windows the "fork" will fail with
    # a PickleError for Python modules that cannot be pickled.
    self._extraction_worker = worker.EventExtractionWorker(
        resolver_context,
        parser_filter_expression=self._parser_filter_expression,
        process_archive_files=self._process_archive_files,
    )

    if self._hasher_names_string:
        self._extraction_worker.SetHashers(self._hasher_names_string)

    if self._yara_rules_string:
        self._extraction_worker.SetYaraRules(self._yara_rules_string)

    self._StartProfiling()

    logging.debug("Worker: {0!s} (PID: {1:d}) started".format(self._name, self._pid))

    self._status = definitions.PROCESSING_STATUS_RUNNING

    try:
        logging.debug(
            "{0!s} (PID: {1:d}) started monitoring task queue.".format(
                self._name, self._pid
            )
        )

        while not self._abort:
            try:
                task = self._task_queue.PopItem()
            except (errors.QueueClose, errors.QueueEmpty) as exception:
                logging.debug(
                    "ConsumeItems exiting with exception {0:s}.".format(type(exception))
                )
                break

            if isinstance(task, plaso_queue.QueueAbort):
                logging.debug("ConsumeItems exiting, dequeued QueueAbort object.")
                break

            self._ProcessTask(task)

        logging.debug(
            "{0!s} (PID: {1:d}) stopped monitoring task queue.".format(
                self._name, self._pid
            )
        )

    # All exceptions need to be caught here to prevent the process
    # from being killed by an uncaught exception.
    except Exception as exception:  # pylint: disable=broad-except
        logging.warning(
            "Unhandled exception in process: {0!s} (PID: {1:d}).".format(
                self._name, self._pid
            )
        )
        logging.exception(exception)

        self._abort = True

    self._StopProfiling()
    self._extraction_worker = None
    self._parser_mediator = None

    if self._abort:
        self._status = definitions.PROCESSING_STATUS_ABORTED
    else:
        self._status = definitions.PROCESSING_STATUS_COMPLETED

    logging.debug("Worker: {0!s} (PID: {1:d}) stopped".format(self._name, self._pid))

    if isinstance(self._task_queue, multi_process_queue.MultiProcessingQueue):
        self._task_queue.Close(abort=True)
    else:
        self._task_queue.Close()


# 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 _Main(self):
    """The main loop."""
    self._parser_mediator = parsers_mediator.ParserMediator(
        None,
        self._knowledge_base,
        preferred_year=self._preferred_year,
        temporary_directory=self._temporary_directory,
    )

    if self._filter_object:
        self._parser_mediator.SetFilterObject(self._filter_object)

    if self._mount_path:
        self._parser_mediator.SetMountPath(self._mount_path)

    if self._text_prepend:
        self._parser_mediator.SetTextPrepend(self._text_prepend)

    # We need a resolver context per process to prevent multi processing
    # issues with file objects stored in images.
    resolver_context = context.Context()

    # We need to initialize the parser and hasher objects after the process
    # has forked otherwise on Windows the "fork" will fail with
    # a PickleError for Python modules that cannot be pickled.
    self._extraction_worker = worker.EventExtractionWorker(
        resolver_context,
        parser_filter_expression=self._parser_filter_expression,
        process_archive_files=self._process_archive_files,
    )

    if self._hasher_names_string:
        self._extraction_worker.SetHashers(self._hasher_names_string)

    if self._yara_rules_string:
        self._extraction_worker.SetYaraRules(self._yara_rules_string)

    self._StartProfiling()

    logging.debug("Worker: {0!s} (PID: {1:d}) started".format(self._name, self._pid))

    self._status = definitions.PROCESSING_STATUS_RUNNING

    try:
        logging.debug(
            "{0!s} (PID: {1:d}) started monitoring task queue.".format(
                self._name, self._pid
            )
        )

        while not self._abort:
            try:
                task = self._task_queue.PopItem()
            except (errors.QueueClose, errors.QueueEmpty) as exception:
                logging.debug(
                    "ConsumeItems exiting with exception {0:s}.".format(type(exception))
                )
                break

            if isinstance(task, plaso_queue.QueueAbort):
                logging.debug("ConsumeItems exiting, dequeued QueueAbort object.")
                break

            self._ProcessTask(task)

        logging.debug(
            "{0!s} (PID: {1:d}) stopped monitoring task queue.".format(
                self._name, self._pid
            )
        )

    # All exceptions need to be caught here to prevent the process
    # from being killed by an uncaught exception.
    except Exception as exception:  # pylint: disable=broad-except
        logging.warning(
            "Unhandled exception in process: {0!s} (PID: {1:d}).".format(
                self._name, self._pid
            )
        )
        logging.exception(exception)

        self._abort = True

    self._StopProfiling()
    self._extraction_worker = None
    self._parser_mediator = None

    if self._abort:
        self._status = definitions.PROCESSING_STATUS_ABORTED
    else:
        self._status = definitions.PROCESSING_STATUS_COMPLETED

    logging.debug("Worker: {0!s} (PID: {1:d}) stopped".format(self._name, self._pid))

    if isinstance(self._task_queue, multi_process_queue.MultiProcessingQueue):
        self._task_queue.Close(abort=True)
    else:
        try:
            self._task_queue.Close()
        except errors.QueueAlreadyClosed:
            logging.error("Queue for {0:s} was already closed.".format(self.name))