Try to avoid Sugar's shell just crashing and leaving a blank X server

when the PresenceService isn't available on the back-end for whatever
reason, whether mis-configuration, corrupted installation, unexpected
circumstances, or what have you.

This patch makes as few changes as possible to the code,
simply replacing the _ps member with a property that re-attempts
connection on each access until an attempt is successful.
This commit is contained in:
Mike C. Fletcher 2007-04-22 00:23:19 -04:00
parent a0ee487a40
commit a7af5b06cd

View File

@ -132,18 +132,64 @@ class PresenceService(gobject.GObject):
def __init__(self):
"""Initialise the service and connect to events"""
"""Initialise the service and attempt to connect to events
"""
gobject.GObject.__init__(self)
self._objcache = ObjectCache()
self._bus = dbus.SessionBus()
self._ps = dbus.Interface(self._bus.get_object(DBUS_SERVICE,
DBUS_PATH), DBUS_INTERFACE)
self._ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb)
self._ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb)
self._ps.connect_to_signal('ActivityAppeared', self._activity_appeared_cb)
self._ps.connect_to_signal('ActivityDisappeared', self._activity_disappeared_cb)
self._ps.connect_to_signal('ActivityInvitation', self._activity_invitation_cb)
self._ps.connect_to_signal('PrivateInvitation', self._private_invitation_cb)
# attempt to load the interface to the service...
self._get_ps()
_bus_ = None
def _get_bus( self ):
"""Retrieve dbus session-bus or create new"""
if not self._bus_:
self._bus_ = dbus.SessionBus()
return self._bus_
_bus = property(
_get_bus, None, None,
"""DBUS SessionBus object for user-local communications"""
)
_ps_ = None
def _get_ps( self ):
"""Retrieve dbus interface to PresenceService
Also registers for updates from various dbus events on the
interface.
If unable to retrieve the interface, we will temporarily
return an _OfflineInterface object to allow the calling
code to continue functioning as though it had accessed a
real presence service.
If successful, caches the presence service interface
for use by other methods and returns that interface
"""
if not self._ps_:
try:
ps = dbus.Interface(
self._bus.get_object(DBUS_SERVICE,DBUS_PATH),
DBUS_INTERFACE
)
except dbus.exceptions.DBusException, err:
logging.error(
"""Failure retrieving %r interface from the D-BUS service %r %r: %s""",
DBUS_INTERFACE, DBUS_SERVICE, DBUS_PATH, err
)
return _OfflineInterface()
else:
self._ps_ = ps
ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb)
ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb)
ps.connect_to_signal('ActivityAppeared', self._activity_appeared_cb)
ps.connect_to_signal('ActivityDisappeared', self._activity_disappeared_cb)
ps.connect_to_signal('ActivityInvitation', self._activity_invitation_cb)
ps.connect_to_signal('PrivateInvitation', self._private_invitation_cb)
return self._ps_
_ps = property(
_get_ps, None, None,
"""DBUS interface to the PresenceService (services/presence/presenceservice)"""
)
def _new_object(self, object_path):
"""Turn new object path into (cached) Buddy/Activity instance
@ -350,6 +396,35 @@ class PresenceService(gobject.GObject):
return bus_name, object_path
class _OfflineInterface( object ):
"""Offline-presence-service interface
Used to mimic the behaviour of a real PresenceService sufficiently
to avoid crashing client code that expects the given interface.
XXX we could likely return a "MockOwner" object reasonably
easily, but would it be worth it?
"""
def raiseException( self, *args, **named ):
"""Raise dbus.exceptions.DBusException"""
raise dbus.exceptions.DBusException(
"""PresenceService Interface not available"""
)
GetActivities = raiseException
GetActivityById = raiseException
GetBuddies = raiseException
GetBuddyByPublicKey = raiseException
GetOwner = raiseException
GetPreferredConnection = raiseException
def ShareActivity(
self, actid, atype, name, properties,
reply_handler, error_handler,
):
"""Pretend to share and fail..."""
exc = IOError(
"""Unable to share activity as PresenceService is not currenly available"""
)
return error_handler( exc )
class _MockPresenceService(gobject.GObject):
"""Test fixture allowing testing of items that use PresenceService