From be09a8a62a1f5d6fe7876c7fe343392a8fdb6905 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Fri, 21 Jan 2011 22:45:31 +0100 Subject: [PATCH] Catch exceptions thrown by pylast on connection problems --- docs/changes.rst | 7 +++++++ mopidy/frontends/lastfm.py | 25 +++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/docs/changes.rst b/docs/changes.rst index f27a45c9..c0d04102 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -71,6 +71,13 @@ This change log is used to track all major changes to Mopidy. - Fix crash when track object does not contain all the expected meta data. + - Fix crash when response from Last.fm cannot be decoded as UTF-8. (Fixes: + :issue:`37`) + + - Fix crash when response from Last.fm contains invalid XML. + + - Fix crash when response from Last.fm has an invalid HTTP status line. + - Mixers: - Support use of unicode strings for settings specific to diff --git a/mopidy/frontends/lastfm.py b/mopidy/frontends/lastfm.py index 69d1c8bc..62b08174 100644 --- a/mopidy/frontends/lastfm.py +++ b/mopidy/frontends/lastfm.py @@ -1,7 +1,9 @@ +from httplib import HTTPException import logging import multiprocessing import socket import time +from xml.parsers.expat import ExpatError try: import pylast @@ -9,7 +11,7 @@ except ImportError as import_error: from mopidy import OptionalDependencyError raise OptionalDependencyError(import_error) -from mopidy import get_version, settings, SettingsError +from mopidy import settings, SettingsError from mopidy.frontends.base import BaseFrontend from mopidy.utils.process import BaseThread @@ -54,6 +56,18 @@ class LastfmFrontend(BaseFrontend): class LastfmFrontendThread(BaseThread): + # Whenever we call pylast, we catch the following non-pylast exceptions, as + # they are not caught and wrapped by pylast. + # + # socket.error: + # Not reported upstream. + # UnicodeDecodeError: + # http://code.google.com/p/pylast/issues/detail?id=55 + # xml.parsers.expat.ExpatError: + # http://code.google.com/p/pylast/issues/detail?id=58 + # httplib.HTTPException: + # Not reported upstream. + def __init__(self, core_queue, connection): super(LastfmFrontendThread, self).__init__(core_queue) self.name = u'LastfmFrontendThread' @@ -79,7 +93,8 @@ class LastfmFrontendThread(BaseThread): except SettingsError as e: logger.info(u'Last.fm scrobbler not started') logger.debug(u'Last.fm settings error: %s', e) - except (pylast.WSError, socket.error) as e: + except (pylast.WSError, socket.error, UnicodeDecodeError, ExpatError, + HTTPException) as e: logger.error(u'Last.fm connection error: %s', e) def process_message(self, message): @@ -103,7 +118,8 @@ class LastfmFrontendThread(BaseThread): duration=str(duration), track_number=str(track.track_no), mbid=(track.musicbrainz_id or '')) - except (pylast.ScrobblingError, pylast.WSError, socket.error) as e: + except (pylast.ScrobblingError, pylast.WSError, socket.error, + UnicodeDecodeError, ExpatError, HTTPException) as e: logger.warning(u'Last.fm now playing error: %s', e) def stopped_playing(self, track, stop_position): @@ -129,5 +145,6 @@ class LastfmFrontendThread(BaseThread): track_number=str(track.track_no), duration=str(duration), mbid=(track.musicbrainz_id or '')) - except (pylast.ScrobblingError, pylast.WSError, socket.error) as e: + except (pylast.ScrobblingError, pylast.WSError, socket.error, + UnicodeDecodeError, ExpatError, HTTPException) as e: logger.warning(u'Last.fm scrobbling error: %s', e)