diff --git a/mopidy/frontends/mpd/dispatcher.py b/mopidy/frontends/mpd/dispatcher.py index f5c30b23..a72789f1 100644 --- a/mopidy/frontends/mpd/dispatcher.py +++ b/mopidy/frontends/mpd/dispatcher.py @@ -1,10 +1,12 @@ +import logging import re +from pykka import ActorDeadError from pykka.registry import ActorRegistry from mopidy.backends.base import Backend from mopidy.frontends.mpd.exceptions import (MpdAckError, MpdArgError, - MpdUnknownCommand) + MpdUnknownCommand, MpdSystemError) from mopidy.frontends.mpd.protocol import mpd_commands, request_handlers # Do not remove the following import. The protocol modules must be imported to # get them registered as request handlers. @@ -16,6 +18,8 @@ from mopidy.frontends.mpd.protocol import (audio_output, command_list, from mopidy.mixers.base import BaseMixer from mopidy.utils import flatten +logger = logging.getLogger('mopidy.frontends.mpd.dispatcher') + class MpdDispatcher(object): """ The MPD session feeds the MPD dispatcher with requests. The dispatcher @@ -49,6 +53,10 @@ class MpdDispatcher(object): if command_list_index is not None: e.index = command_list_index return self.handle_response(e.get_mpd_ack(), add_ok=False) + except ActorDeadError as e: + logger.warning(u'Tried to communicate with dead actor.') + mpd_error = MpdSystemError(e.message) + return self.handle_response(mpd_error.get_mpd_ack(), add_ok=False) if request in (u'command_list_begin', u'command_list_ok_begin'): return None if command_list_index is not None: diff --git a/mopidy/frontends/mpd/exceptions.py b/mopidy/frontends/mpd/exceptions.py index faf4ce2f..df90aed7 100644 --- a/mopidy/frontends/mpd/exceptions.py +++ b/mopidy/frontends/mpd/exceptions.py @@ -54,6 +54,11 @@ class MpdNoExistError(MpdAckError): super(MpdNoExistError, self).__init__(*args, **kwargs) self.error_code = MpdAckError.ACK_ERROR_NO_EXIST +class MpdSystemError(MpdAckError): + def __init__(self, *args, **kwargs): + super(MpdSystemError, self).__init__(*args, **kwargs) + self.error_code = MpdAckError.ACK_ERROR_SYSTEM + class MpdNotImplemented(MpdAckError): def __init__(self, *args, **kwargs): super(MpdNotImplemented, self).__init__(*args, **kwargs) diff --git a/mopidy/utils/process.py b/mopidy/utils/process.py index dbc6cada..7f6cf664 100644 --- a/mopidy/utils/process.py +++ b/mopidy/utils/process.py @@ -4,6 +4,8 @@ import threading import gobject gobject.threads_init() +from pykka import ActorDeadError + from mopidy import SettingsError logger = logging.getLogger('mopidy.utils.process') @@ -21,26 +23,19 @@ class BaseThread(threading.Thread): self.run_inside_try() except KeyboardInterrupt: logger.info(u'Interrupted by user') - self.exit(0, u'Interrupted by user') except SettingsError as e: logger.error(e.message) - self.exit(1, u'Settings error') except ImportError as e: logger.error(e) - self.exit(2, u'Import error') + except ActorDeadError as e: + logger.warning(e) except Exception as e: logger.exception(e) - self.exit(3, u'Unknown error') + logger.debug(u'%s: Exiting thread', self.name) def run_inside_try(self): raise NotImplementedError - def destroy(self): - pass - - def exit(self, status=0, reason=None): - self.destroy() - class GObjectEventThread(BaseThread): """ diff --git a/tests/frontends/mpd/exception_test.py b/tests/frontends/mpd/exception_test.py index ef222d46..9b1b47a2 100644 --- a/tests/frontends/mpd/exception_test.py +++ b/tests/frontends/mpd/exception_test.py @@ -1,7 +1,7 @@ import unittest from mopidy.frontends.mpd.exceptions import (MpdAckError, MpdUnknownCommand, - MpdNotImplemented) + MpdSystemError, MpdNotImplemented) class MpdExceptionsTest(unittest.TestCase): def test_key_error_wrapped_in_mpd_ack_error(self): @@ -36,3 +36,10 @@ class MpdExceptionsTest(unittest.TestCase): except MpdAckError as e: self.assertEqual(e.get_mpd_ack(), u'ACK [5@0] {} unknown command "play"') + + def test_mpd_system_error(self): + try: + raise MpdSystemError('foo') + except MpdSystemError as e: + self.assertEqual(e.get_mpd_ack(), + u'ACK [52@0] {} foo')