From ae2cdf0fad921e6ac805fcc0366979f3ae177f0d Mon Sep 17 00:00:00 2001 From: Jamie Strandboge Date: Tue, 9 Apr 2013 08:31:39 -0500 Subject: [PATCH] Fix two race conditions: 1) make sure that the xpra socket exists before trying to attach to it 2) make sure that the client has attached before we start the application The fix for '1' solves a problem when the system is under load and the one for '2' fixes a problem with firefox starting too soon and not having system themes applied. Exercising the 1 week rule. Seth Arnold commented on the added sleeps and I adjusted one based on his comments and replied to the list that the other is needed and that this improves the sandbox/xpra code but that there are limitations with driving xpra. Acked-By: Jamie Strandboge --- utils/apparmor/sandbox.py | 45 ++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/utils/apparmor/sandbox.py b/utils/apparmor/sandbox.py index 4171ef4f0..dc2d19151 100644 --- a/utils/apparmor/sandbox.py +++ b/utils/apparmor/sandbox.py @@ -1,6 +1,6 @@ # ------------------------------------------------------------------ # -# Copyright (C) 2011-2012 Canonical Ltd. +# Copyright (C) 2011-2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or # modify it under the terms of version 2 of the GNU General Public @@ -15,6 +15,7 @@ import os import pwd import re import signal +import socket import sys import tempfile import time @@ -605,13 +606,36 @@ EndSection self.pids.append(listener_x) started = False - time.sleep(0.5) # FIXME: detect if running - for i in range(self.timeout): # 5 seconds to start + + # We need to wait for the xpra socket to exist before attaching + fn = os.path.join(os.environ['HOME'], '.xpra', '%s-%s' % \ + (socket.gethostname(), self.display.split(':')[1])) + for i in range(self.timeout * 2): # up to self.timeout seconds to start + if os.path.exists(fn): + debug("Found '%s'! Proceeding to attach" % fn) + break + debug("'%s' doesn't exist yet, waiting" % fn) + time.sleep(0.5) + + if not os.path.exists(fn): + sys.stdout.flush() + self.cleanup() + raise AppArmorException("Could not start xpra (try again with -d)") + + for i in range(self.timeout): # Up to self.timeout seconds to start rc, out = cmd(['xpra', 'list']) - if 'LIVE session at %s' % self.display in out: + + if 'DEAD session at %s' % self.display in out: + error("xpra session at '%s' died" % self.display, do_exit=False) + break + + search = 'LIVE session at %s' % self.display + if search in out: started = True break - time.sleep(1) + time.sleep(0.5) + debug("Could not find '%s' in:\n" % search) + debug(out) if not started: sys.stdout.flush() @@ -638,6 +662,17 @@ EndSection self.pids.append(listener_attach) + # Make sure that a client has attached + for i in range(self.timeout): # up to self.timeout seconds to attach + time.sleep(1) + rc, out = cmd (['xpra', 'info', self.display]) + search = 'clients=1' + if search in out: + debug("Client successfully attached!") + break + debug("Could not find '%s' in:\n" % search) + debug(out) + msg("TODO: filter '~/.xpra/run-xpra'")