Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/sugar/activity/activityfactory.py
diff options
context:
space:
mode:
authorMichael Stone <michael@laptop.org>2009-02-27 21:42:47 (GMT)
committer Michael Stone <michael@laptop.org>2009-02-27 21:42:47 (GMT)
commita65c8d2148ba5028437114049027e594238f2ed8 (patch)
tree36aa833a93a81fac68069fa1a487855b1c19408a /src/sugar/activity/activityfactory.py
parent6f210f0e33786570fcdb8235a41c2f9009e78576 (diff)
Get activities launching with rainbow-0.8.x.
Future extensions: a) we are now able to reliably detect when an activity's main process has exited. We should take advantage of this to give better feedback on activity crashes; e.g. by turning the frame's activity-icon into an error icon and by inserting the activity's log into the datastore so that it appears in the Journal. b) in the future, I'd like rainbow to provide more narrow interfaces for manipulating jails; e.g. for garbage-collecting them, nuking their contents, or for reusing them. Please consider this an invitation to show me which interfaces would work best for Sugar. P.S. - Thanks to Sascha Silbe for testing and for improvements to this patch.
Diffstat (limited to 'src/sugar/activity/activityfactory.py')
-rw-r--r--src/sugar/activity/activityfactory.py82
1 files changed, 44 insertions, 38 deletions
diff --git a/src/sugar/activity/activityfactory.py b/src/sugar/activity/activityfactory.py
index e218a7c..c31ae4b 100644
--- a/src/sugar/activity/activityfactory.py
+++ b/src/sugar/activity/activityfactory.py
@@ -34,6 +34,9 @@ from sugar import env
from errno import EEXIST, ENOSPC
import os
+import tempfile
+import subprocess
+import pwd
_SHELL_SERVICE = "org.laptop.Shell"
_SHELL_PATH = "/org/laptop/Shell"
@@ -45,10 +48,6 @@ _DS_PATH = "/org/laptop/sugar/DataStore"
_ACTIVITY_FACTORY_INTERFACE = "org.laptop.ActivityFactory"
-_RAINBOW_SERVICE_NAME = "org.laptop.security.Rainbow"
-_RAINBOW_ACTIVITY_FACTORY_PATH = "/"
-_RAINBOW_ACTIVITY_FACTORY_INTERFACE = "org.laptop.security.Rainbow"
-
# helper method to close all filedescriptors
# borrowed from subprocess.py
try:
@@ -253,40 +252,47 @@ class ActivityCreationHandler(gobject.GObject):
self._handle.object_id,
self._handle.uri)
- if not self._use_rainbow:
- # use gobject spawn functionality, so that zombies are
- # automatically reaped by the gobject event loop.
- def child_setup():
- # clone logfile.fileno() onto stdout/stderr
- os.dup2(log_file.fileno(), 1)
- os.dup2(log_file.fileno(), 2)
- # close all other fds
- _close_fds()
- # we need to sanitize and str-ize the various bits which
- # dbus gives us.
- gobject.spawn_async([str(s) for s in command],
- envp=['%s=%s' % (k, str(v))
- for k, v in environ.items()],
- working_directory=str(self._bundle.get_path()),
- child_setup=child_setup,
- flags=(gobject.SPAWN_SEARCH_PATH |
- gobject.SPAWN_LEAVE_DESCRIPTORS_OPEN))
- log_file.close()
- else:
- log_file.close()
- system_bus = dbus.SystemBus()
- factory = system_bus.get_object(_RAINBOW_SERVICE_NAME,
- _RAINBOW_ACTIVITY_FACTORY_PATH)
- factory.CreateActivity(
- log_path,
- environ,
- command,
- environ['SUGAR_BUNDLE_PATH'],
- environ['SUGAR_BUNDLE_ID'],
- timeout=30,
- reply_handler=self._create_reply_handler,
- error_handler=self._create_error_handler,
- dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE)
+ envdir = None
+ if self._use_rainbow:
+ envdir = tempfile.mkdtemp()
+ command = ['/usr/bin/sudo', '-E', '--',
+ '/usr/bin/rainbow-run',
+ '-v', '-v',
+ '-a', '/usr/bin/rainbow-sugarize',
+ '-s', '/var/spool/rainbow/2',
+ '-f', '1',
+ '-f', '2',
+ '-c', self._bundle.get_path(),
+ '-u', pwd.getpwuid(os.getuid()).pw_name,
+ '-i', environ['SUGAR_BUNDLE_ID'],
+ '-e', envdir,
+ '--'
+ ] + command
+ for k, v in environ.items():
+ open(os.path.join(envdir, str(k)), 'w').write(str(v))
+ log_file.write(' '.join(command) + '\n\n')
+
+ def handler(pid, condition, user_data):
+ if envdir: subprocess.call(['/bin/rm', '-rf', envdir])
+ try:
+ log_file.write('Activity died: pid %s condition %s data %s\n' %
+ (pid, condition, user_data))
+ finally:
+ log_file.close()
+
+ # try to reap zombies in case SIGCHLD has not been set to SIG_IGN
+ try :
+ os.waitpid(pid, 0)
+ except OSError:
+ # SIGCHLD = SIG_IGN, no zombies
+ pass
+
+ devnull = file("/dev/null", "r")
+ child = subprocess.Popen([str(s) for s in command], env=environ,
+ cwd=str(self._bundle.get_path()), close_fds=True,
+ stdin=devnull.fileno(), stdout=log_file.fileno(),
+ stderr=log_file.fileno())
+ gobject.child_watch_add(child.pid, handler, self._handle.activity_id)
def _no_reply_handler(self, *args):
pass