Improve ActivityFactory utility functions and reduce code-path duplication.

* Remove a race in open_log_file()

  * Make open_log_file return a path as well as a file-object so that
    Rainbow-launched activities can log to the same path that sugar-launched
    ones do.

  * Change the call to Rainbow so that it writes to the log-file provided by
    open_log_file()

  * Define SUGAR_BUNDLE_ID env variable and change the location of the check
    for /etc/olpc-security so that Rainbow doesn't have to search for or parse
    the activity bundle.

  * Remove import statements marked as unnecessary by pylint.

  * Fix up some whitespace issues.
This commit is contained in:
Michael Stone 2007-11-05 13:55:56 -05:00
parent 9e4b78766b
commit 0a9676171d

View File

@ -21,12 +21,10 @@ import subprocess
import dbus import dbus
import gobject import gobject
import gtk
from sugar.presence import presenceservice from sugar.presence import presenceservice
from sugar.activity.activityhandle import ActivityHandle from sugar.activity.activityhandle import ActivityHandle
from sugar.activity import registry from sugar.activity import registry
from sugar.datastore import datastore
from sugar import util from sugar import util
from sugar import env from sugar import env
@ -93,6 +91,7 @@ def get_environment(activity):
os.mkdir(tmp_dir) os.mkdir(tmp_dir)
environ['SUGAR_BUNDLE_PATH'] = activity.path environ['SUGAR_BUNDLE_PATH'] = activity.path
environ['SUGAR_BUNDLE_ID'] = activity.bundle_id
environ['SUGAR_ACTIVITY_ROOT'] = activity_root environ['SUGAR_ACTIVITY_ROOT'] = activity_root
environ['PATH'] = bin_path + ':' + environ['PATH'] environ['PATH'] = bin_path + ':' + environ['PATH']
@ -115,41 +114,47 @@ def get_command(activity, activity_id=None, object_id=None, uri=None):
return command return command
def open_log_file(activity, activity_id): def open_log_file(activity):
for i in range(1, 100): i = 1
while True:
path = env.get_logs_path('%s-%s.log' % (activity.bundle_id, i)) path = env.get_logs_path('%s-%s.log' % (activity.bundle_id, i))
if not os.path.exists(path): try:
return open(path, 'w') fd = os.open(path, os.O_EXCL | os.O_CREAT \
| os.O_SYNC | os.O_WRONLY, 0644)
f = os.fdopen(fd, 'w', 0)
return (path, f)
except:
i += 1
class ActivityCreationHandler(gobject.GObject): class ActivityCreationHandler(gobject.GObject):
"""Sugar-side activity creation interface """Sugar-side activity creation interface
This object uses a dbus method on the ActivityFactory This object uses a dbus method on the ActivityFactory
service to create the new activity. It generates service to create the new activity. It generates
GObject events in response to the success/failure of GObject events in response to the success/failure of
activity startup using callbacks to the service's activity startup using callbacks to the service's
create call. create call.
""" """
def __init__(self, service_name, handle): def __init__(self, service_name, handle):
"""Initialise the handler """Initialise the handler
service_name -- the service name of the bundle factory service_name -- the service name of the bundle factory
activity_handle -- stores the values which are to activity_handle -- stores the values which are to
be passed to the service to uniquely identify be passed to the service to uniquely identify
the activity to be created and the sharing the activity to be created and the sharing
service that may or may not be connected with it service that may or may not be connected with it
sugar.activity.activityhandle.ActivityHandle instance sugar.activity.activityhandle.ActivityHandle instance
calls the "create" method on the service for this calls the "create" method on the service for this
particular activity type and registers the particular activity type and registers the
_reply_handler and _error_handler methods on that _reply_handler and _error_handler methods on that
call's results. call's results.
The specific service which creates new instances of this The specific service which creates new instances of this
particular type of activity is created during the activity particular type of activity is created during the activity
registration process in shell bundle registry which creates registration process in shell bundle registry which creates
service definition files for each registered bundle type. service definition files for each registered bundle type.
If the file '/etc/olpc-security' exists, then activity launching If the file '/etc/olpc-security' exists, then activity launching
@ -184,37 +189,40 @@ class ActivityCreationHandler(gobject.GObject):
def _create_activity(self): def _create_activity(self):
if self._handle.activity_id is None: if self._handle.activity_id is None:
self._handle.activity_id = create_activity_id() self._handle.activity_id = create_activity_id()
self._shell.NotifyLaunch( self._shell.NotifyLaunch(
self._service_name, self._handle.activity_id, self._service_name, self._handle.activity_id,
reply_handler=self._no_reply_handler, reply_handler=self._no_reply_handler,
error_handler=self._notify_launch_error_handler) error_handler=self._notify_launch_error_handler)
if not os.path.exists('/etc/olpc-security'): activity_registry = registry.get_registry()
activity_registry = registry.get_registry() activity = activity_registry.get_activity(self._service_name)
activity = activity_registry.get_activity(self._service_name) if activity:
if activity: environ = get_environment(activity)
env = get_environment(activity) (log_path, log_file) = open_log_file(activity)
log_file = open_log_file(activity, self._handle.activity_id) command = get_command(activity, self._handle.activity_id,
command = get_command(activity, self._handle.activity_id, self._handle.object_id,
self._handle.object_id, self._handle.uri)
self._handle.uri)
process = subprocess.Popen(command, env=env, cwd=activity.path, if not os.path.exists('/etc/olpc-security'):
process = subprocess.Popen(command, env=environ, cwd=activity.path,
stdout=log_file, stderr=log_file) stdout=log_file, stderr=log_file)
else: else:
system_bus = dbus.SystemBus() log_file.close()
factory = system_bus.get_object(_RAINBOW_SERVICE_NAME, system_bus = dbus.SystemBus()
_RAINBOW_ACTIVITY_FACTORY_PATH) factory = system_bus.get_object(_RAINBOW_SERVICE_NAME,
stdio_paths = {'stdout': '/logs/stdout', 'stderr': '/logs/stderr'} _RAINBOW_ACTIVITY_FACTORY_PATH)
factory.CreateActivity( factory.CreateActivity(
self._service_name, log_path,
self._handle.get_dict(), environ,
stdio_paths, command,
timeout=120 * DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND, environ['SUGAR_BUNDLE_PATH'],
reply_handler=self._create_reply_handler, environ['SUGAR_BUNDLE_ID'],
error_handler=self._create_error_handler, timeout=30 * DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND,
dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE) reply_handler=self._create_reply_handler,
error_handler=self._create_error_handler,
dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE)
def _no_reply_handler(self, *args): def _no_reply_handler(self, *args):
pass pass
@ -233,7 +241,7 @@ class ActivityCreationHandler(gobject.GObject):
logging.error("Activity activation request failed %s" % err) logging.error("Activity activation request failed %s" % err)
def _create_reply_handler(self, xid): def _create_reply_handler(self, xid):
logging.debug("Activity created %s (%s)." % logging.debug("Activity created %s (%s)." %
(self._handle.activity_id, self._service_name)) (self._handle.activity_id, self._service_name))
def _create_error_handler(self, err): def _create_error_handler(self, err):