Inhibit suspend while a activity is shared

In some network environments, suspend/reume can make loose
messages and break collaboration. This patch inhibit suspend
when collaboration start. The implementation can be used by activities
or Sugar to inhibit suspend/resume when needed.

More information in http://dev.laptop.org/ticket/10363

Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
This commit is contained in:
Gonzalo Odiard 2013-12-27 12:00:22 -03:00
parent cf7a5905fd
commit 62b60fa1e1
3 changed files with 96 additions and 0 deletions

View File

@ -14,6 +14,7 @@ sugar_PYTHON = \
logger.py \ logger.py \
mime.py \ mime.py \
network.py \ network.py \
power.py \
profile.py \ profile.py \
util.py util.py

View File

@ -74,6 +74,7 @@ from telepathy.constants import CONNECTION_HANDLE_TYPE_CONTACT
from telepathy.constants import CONNECTION_HANDLE_TYPE_ROOM from telepathy.constants import CONNECTION_HANDLE_TYPE_ROOM
from sugar3 import util from sugar3 import util
from sugar3 import power
from sugar3.presence import presenceservice from sugar3.presence import presenceservice
from sugar3.activity.activityservice import ActivityService from sugar3.activity.activityservice import ActivityService
from sugar3.graphics import style from sugar3.graphics import style
@ -809,6 +810,10 @@ class Activity(Window, Gtk.Container):
logging.debug('Failed to join activity: %s' % err) logging.debug('Failed to join activity: %s' % err)
return return
power_manager = power.get_power_manager()
if power_manager.suspend_breaks_collaboration():
power_manager.inhibit_suspend()
self.reveal() self.reveal()
self.emit('joined') self.emit('joined')
self.__privacy_changed_cb(self.shared_activity, None) self.__privacy_changed_cb(self.shared_activity, None)
@ -837,6 +842,10 @@ class Activity(Window, Gtk.Container):
activity.props.name = self._jobject.metadata['title'] activity.props.name = self._jobject.metadata['title']
power_manager = power.get_power_manager()
if power_manager.suspend_breaks_collaboration():
power_manager.inhibit_suspend()
self.shared_activity = activity self.shared_activity = activity
self.shared_activity.connect('notify::private', self.shared_activity.connect('notify::private',
self.__privacy_changed_cb) self.__privacy_changed_cb)
@ -953,6 +962,7 @@ class Activity(Window, Gtk.Container):
dbus.service.Object.remove_from_connection(self._bus) dbus.service.Object.remove_from_connection(self._bus)
self._session.unregister(self) self._session.unregister(self)
power.get_power_manager().shutdown()
def close(self, skip_save=False): def close(self, skip_save=False):
"""Request that the activity be stopped and saved to the Journal """Request that the activity be stopped and saved to the Journal

85
src/sugar3/power.py Normal file
View File

@ -0,0 +1,85 @@
# Copyright (C) 2014, Sugarlabs
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import os
import logging
_POWERD_INHIBIT_DIR = '/var/run/powerd-inhibit-suspend'
_power_manager = None
def get_power_manager():
global _power_manager
if _power_manager is None:
_power_manager = PowerManager()
return _power_manager
class PowerManager():
""" control of powerd idle suspend,
reference counted,
does nothing if powerd is not present
"""
def __init__(self):
self._suspend_inhibit_counter = 0
def __del__(self):
self._remove_flag_file()
def suspend_breaks_collaboration(self):
return True
def inhibit_suspend(self):
if not os.path.exists(_POWERD_INHIBIT_DIR):
return
if self._suspend_inhibit_counter == 0:
path = os.path.join(_POWERD_INHIBIT_DIR, str(os.getpid()))
try:
with open(path, 'w') as flag_file:
flag_file.write('')
except IOError:
logging.error("Inhibit Suspend: Could not create file %s",
path)
self._suspend_inhibit_counter += 1
def restore_suspend(self):
self._suspend_inhibit_counter -= 1
if self._suspend_inhibit_counter > 0:
return
self._remove_flag_file()
def is_suspend_inhibited(self):
return self._suspend_inhibit_counter > 0
def shutdown(self):
"""
This method clean the flag file if exists,
is already called when the activity is closed.
"""
self._remove_flag_file()
def _remove_flag_file(self):
path = os.path.join(_POWERD_INHIBIT_DIR, str(os.getpid()))
try:
os.unlink(path)
except IOError:
logging.error("Inhibit Suspend: Could not delete file %s", path)
self._suspend_inhibit_counter = 0