示例#1
0
def run_executable(cmd, build_dir, env):
  """Runs an executable within a xvfb buffer on linux or normally on other
  platforms.

  Requires that both xvfb and icewm are installed on linux.

  Detects recursion with an environment variable and do not create a recursive X
  buffer if present.
  """
  # First look if we are inside a display.
  if env.get('_CHROMIUM_INSIDE_XVFB') == '1':
    # No need to recurse.
    return test_env.run_executable(cmd, env)

  pid = None
  xvfb = 'Xvfb'
  try:
    if sys.platform == 'linux2':
      # Defaults to X display 9.
      display = ':9'
      pid = start_xvfb(xvfb, display)
      env['DISPLAY'] = display
      if not wait_for_xvfb(os.path.join(build_dir, 'xdisplaycheck'), env):
        return 3
      # Inhibit recursion.
      env['_CHROMIUM_INSIDE_XVFB'] = '1'
      # Some ChromeOS tests need a window manager. Technically, it could be
      # another script but that would be overkill.
      subprocess.Popen(
          'icewm', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
    return test_env.run_executable(cmd, env)
  finally:
    if pid:
      kill(pid)
示例#2
0
def run_executable(cmd, env):
  """Runs an executable within Xvfb on Linux or normally on other platforms.

  Returns the exit code of the specified commandline, or 1 on failure.
  """
  if sys.platform == 'linux2':
    if env.get('_CHROMIUM_INSIDE_XVFB') == '1':
      openbox_proc = None
      xcompmgr_proc = None
      try:
        # Some ChromeOS tests need a window manager.
        openbox_proc = subprocess.Popen('openbox', stdout=subprocess.PIPE,
                                        stderr=subprocess.STDOUT, env=env)

        # Some tests need a compositing wm to make use of transparent visuals.
        xcompmgr_proc = subprocess.Popen('xcompmgr', stdout=subprocess.PIPE,
                                         stderr=subprocess.STDOUT, env=env)

        return test_env.run_executable(cmd, env)
      except OSError as e:
        print >> sys.stderr, 'Failed to start Xvfb or Openbox: %s' % str(e)
        return 1
      finally:
        kill(openbox_proc)
        kill(xcompmgr_proc)
    else:
      env['_CHROMIUM_INSIDE_XVFB'] = '1'
      return subprocess.call(['xvfb-run', '-a', "--server-args=-screen 0 "
                              "1280x800x24 -ac -nolisten tcp -dpi 96",
                              __file__] + cmd, env=env)
  else:
    return test_env.run_executable(cmd, env)
示例#3
0
def run_executable(cmd, build_dir, env):
  """Runs an executable within a xvfb buffer on linux or normally on other
  platforms.

  Requires that both xvfb and openbox are installed on linux.

  Detects recursion with an environment variable and do not create a recursive X
  buffer if present.
  """
  # First look if we are inside a display.
  if env.get('_CHROMIUM_INSIDE_XVFB') == '1':
    # No need to recurse.
    return test_env.run_executable(cmd, env)

  xvfb_proc = None
  xvfb = 'Xvfb'
  try:
    if sys.platform == 'linux2':
      # Defaults to X display 9.
      display = ':9'
      xvfb_proc = start_xvfb(xvfb, display)
      if not xvfb_proc or not xvfb_proc.pid:
        return 1
      env['DISPLAY'] = display
      if not wait_for_xvfb(os.path.join(build_dir, 'xdisplaycheck'), env):
        rc = xvfb_proc.poll()
        if rc is None:
          print 'Xvfb still running, stopping.'
          xvfb_proc.terminate()
        else:
          print 'Xvfb exited, code %d' % rc

        print 'Xvfb output:'
        for l in xvfb_proc.communicate()[0].splitlines():
          print '> %s' % l

        return 3
      # Inhibit recursion.
      env['_CHROMIUM_INSIDE_XVFB'] = '1'
      # Some ChromeOS tests need a window manager. Technically, it could be
      # another script but that would be overkill.
      try:
        wm_cmd = ['openbox']
        subprocess.Popen(
            wm_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
      except OSError:
        print >> sys.stderr, 'Failed to run %s' % ' '.join(wm_cmd)
        return 1
    return test_env.run_executable(cmd, env)
  finally:
    # When the X server dies, it takes down the window manager with it.
    if xvfb_proc and xvfb_proc.pid:
      kill(xvfb_proc.pid)
示例#4
0
def run_executable(cmd, env):
  """Runs an executable within Xvfb on Linux or normally on other platforms.

  Returns the exit code of the specified commandline, or 1 on failure.
  """

  # It might seem counterintuitive to support a --no-xvfb flag in a script
  # whose only job is to start xvfb, but doing so allows us to consolidate
  # the logic in the layers of buildbot scripts so that we *always* use
  # xvfb by default and don't have to worry about the distinction, it
  # can remain solely under the control of the test invocation itself.
  use_xvfb = True
  if '--no-xvfb' in cmd:
    use_xvfb = False
    cmd.remove('--no-xvfb')

  if sys.platform == 'linux2' and use_xvfb:
    if env.get('_CHROMIUM_INSIDE_XVFB') == '1':
      openbox_proc = None
      xcompmgr_proc = None
      try:
        # Some ChromeOS tests need a window manager.
        openbox_proc = subprocess.Popen('openbox', stdout=subprocess.PIPE,
                                        stderr=subprocess.STDOUT, env=env)

        # Some tests need a compositing wm to make use of transparent visuals.
        xcompmgr_proc = subprocess.Popen('xcompmgr', stdout=subprocess.PIPE,
                                         stderr=subprocess.STDOUT, env=env)

        return test_env.run_executable(cmd, env)
      except OSError as e:
        print >> sys.stderr, 'Failed to start Xvfb or Openbox: %s' % str(e)
        return 1
      finally:
        kill(openbox_proc)
        kill(xcompmgr_proc)
    else:
      env['_CHROMIUM_INSIDE_XVFB'] = '1'
      xvfb_script = __file__
      if xvfb_script.endswith('.pyc'):
        xvfb_script = xvfb_script[:-1]
      return subprocess.call(['xvfb-run', '-a', "--server-args=-screen 0 "
                              "1280x800x24 -ac -nolisten tcp -dpi 96",
                              xvfb_script] + cmd, env=env)
  else:
    return test_env.run_executable(cmd, env)
示例#5
0
文件: xvfb.py 项目: a397871706/plug
def run_executable(cmd, build_dir, env):
  """Runs an executable within Xvfb on Linux or normally on other platforms.

  Returns the exit code of the specified commandline, or 1 on failure.
  """
  xvfb = None
  openbox = None
  if should_start_xvfb(env):
    (xvfb, openbox) = start_xvfb(env, build_dir)
    if not xvfb or not xvfb.pid or not openbox or not openbox.pid:
      return 1
  try:
    return test_env.run_executable(cmd, env)
  finally:
    kill(xvfb)
    kill(openbox)
示例#6
0
def run_executable(cmd, build_dir, env):
  """Runs an executable within a xvfb buffer on linux or normally on other
  platforms.

  Requires that both xvfb and icewm are installed on linux.
  """
  pid = None
  xvfb = 'Xvfb'
  try:
    if sys.platform == 'linux2':
      # Defaults to X display 9.
      display = ':9'
      pid = start_xvfb(xvfb, display)
      env['DISPLAY'] = display
      if not wait_for_xvfb(os.path.join(build_dir, 'xdisplaycheck'), env):
        return 3
      # Some ChromeOS tests need a window manager. Technically, it could be
      # another script but that would be overkill.
      subprocess.Popen(
          'icewm', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
    return test_env.run_executable(cmd, env)
  finally:
    if pid:
      kill(pid)
示例#7
0
def _run_with_weston(cmd, env, stdoutfile):
  weston_proc = None

  try:
    signal.signal(signal.SIGTERM, raise_weston_error)
    signal.signal(signal.SIGINT, raise_weston_error)

    dbus_pid = launch_dbus(env)

    # The bundled weston (//third_party/weston) is used by Linux Ozone Wayland
    # CI and CQ testers and compiled by //ui/ozone/platform/wayland whenever
    # there is a dependency on the Ozone/Wayland and use_bundled_weston is set
    # in gn args. However, some tests do not require Wayland or do not use
    # //ui/ozone at all, but still have --use-weston flag set by the
    # OZONE_WAYLAND variant (see //testing/buildbot/variants.pyl). This results
    # in failures and those tests cannot be run because of the exception that
    # informs about missing weston binary. Thus, to overcome the issue before
    # a better solution is found, add a check for the "weston" binary here and
    # run tests without Wayland compositor if the weston binary is not found.
    # TODO(https://1178788): find a better solution.
    if not os.path.isfile("./weston"):
      print('Weston is not available. Starting without Wayland compositor')
      return test_env.run_executable(cmd, env, stdoutfile)

    # Set $XDG_RUNTIME_DIR if it is not set.
    _set_xdg_runtime_dir(env)

    # Weston is compiled along with the Ozone/Wayland platform, and is
    # fetched as data deps. Thus, run it from the current directory.
    #
    # Weston is used with the following flags:
    # 1) --backend=headless-backend.so - runs Weston in a headless mode
    # that does not require a real GPU card.
    # 2) --idle-time=0 - disables idle timeout, which prevents Weston
    # to enter idle state. Otherwise, Weston stops to send frame callbacks,
    # and tests start to time out (this typically happens after 300 seconds -
    # the default time after which Weston enters the idle state).
    # 3) --width && --height set size of a virtual display: we need to set
    # an adequate size so that tests can have more room for managing size
    # of windows.
    # 4) --use-gl - Runs Weston using hardware acceleration instead of
    # SwiftShader.
    weston_cmd = ['./weston', '--backend=headless-backend.so', '--idle-time=0',
          '--width=1024', '--height=768', '--modules=test-plugin.so']

    if '--weston-use-gl' in cmd:
      weston_cmd.append('--use-gl')
      cmd.remove('--weston-use-gl')

    if '--weston-debug-logging' in cmd:
      cmd.remove('--weston-debug-logging')
      env = copy.deepcopy(env)
      env['WAYLAND_DEBUG'] = '1'

    weston_proc_display = None
    for _ in range(10):
      weston_proc = subprocess.Popen(
         weston_cmd,
         stderr=subprocess.STDOUT, env=env)

      # Get the $WAYLAND_DISPLAY set by Weston and pass it to the test launcher.
      # Please note that this env variable is local for the process. That's the
      # reason we have to read it from Weston separately.
      weston_proc_display = _get_display_from_weston(weston_proc.pid)
      if weston_proc_display is not None:
        break # Weston could launch and we found the display.

    # If we couldn't find the display after 10 tries, raise an exception.
    if weston_proc_display is None:
      raise _WestonProcessError('Failed to start Weston.')
    env['WAYLAND_DISPLAY'] = weston_proc_display
    return test_env.run_executable(cmd, env, stdoutfile)
  except OSError as e:
    print('Failed to start Weston: %s\n' % str(e), file=sys.stderr)
    return 1
  except _WestonProcessError as e:
    print('Weston fail: %s\n' % str(e), file=sys.stderr)
    return 1
  finally:
    kill(weston_proc, 'weston')

    # dbus-daemon is not a subprocess, so we can't SIGTERM+waitpid() on it.
    # To ensure it exits, use SIGKILL which should be safe since all other
    # processes that it would have been servicing have exited.
    if dbus_pid:
      os.kill(dbus_pid, signal.SIGKILL)
示例#8
0
def _run_with_xvfb(cmd, env, stdoutfile, use_openbox, use_xcompmgr):
  openbox_proc = None
  xcompmgr_proc = None
  xvfb_proc = None
  xwmstartupcheck_proc = None
  xvfb_ready = MutableBoolean()
  def set_xvfb_ready(*_):
    xvfb_ready.setvalue(True)

  dbus_pid = None
  try:
    signal.signal(signal.SIGTERM, raise_xvfb_error)
    signal.signal(signal.SIGINT, raise_xvfb_error)

    # Before [1], the maximum number of X11 clients was 256.  After, the default
    # limit is 256 with a configurable maximum of 512.  On systems with a large
    # number of CPUs, the old limit of 256 may be hit for certain test suites
    # [2] [3], so we set the limit to 512 when possible.  This flag is not
    # available on Ubuntu 16.04 or 18.04, so a feature check is required.  Xvfb
    # does not have a '-version' option, so checking the '-help' output is
    # required.
    #
    # [1] d206c240c0b85c4da44f073d6e9a692afb6b96d2
    # [2] https://crbug.com/1187948
    # [3] https://crbug.com/1120107
    xvfb_help = subprocess.check_output(
      ['Xvfb', '-help'], stderr=subprocess.STDOUT).decode('utf8')

    # Due to race condition for display number, Xvfb might fail to run.
    # If it does fail, try again up to 10 times, similarly to xvfb-run.
    for _ in range(10):
      xvfb_ready.setvalue(False)
      display = find_display()

      xvfb_cmd = ['Xvfb', display, '-screen', '0', '1280x800x24', '-ac',
                  '-nolisten', 'tcp', '-dpi', '96', '+extension', 'RANDR']
      if '-maxclients' in xvfb_help:
        xvfb_cmd += ['-maxclients', '512']

      # Sets SIGUSR1 to ignore for Xvfb to signal current process
      # when it is ready. Due to race condition, USR1 signal could be sent
      # before the process resets the signal handler, we cannot rely on
      # signal handler to change on time.
      signal.signal(signal.SIGUSR1, signal.SIG_IGN)
      xvfb_proc = subprocess.Popen(xvfb_cmd, stderr=subprocess.STDOUT, env=env)
      signal.signal(signal.SIGUSR1, set_xvfb_ready)
      for _ in range(10):
        time.sleep(.1)  # gives Xvfb time to start or fail.
        if xvfb_ready.getvalue() or xvfb_proc.poll() is not None:
          break  # xvfb sent ready signal, or already failed and stopped.

      if xvfb_proc.poll() is None:
        break  # xvfb is running, can proceed.
    if xvfb_proc.poll() is not None:
      raise _XvfbProcessError('Failed to start after 10 tries')

    env['DISPLAY'] = display
    # Set dummy variable for scripts.
    env['XVFB_DISPLAY'] = display

    dbus_pid = launch_dbus(env)

    if use_openbox:
      # This is not ideal, but x11_unittests require that (other X11 tests have
      # a race with the openbox as well, but they take more time to initialize.
      # And thus, they do no time out compate to the x11_unittests that are
      # quick enough to start up before openbox is ready.
      # TODO(dpranke): remove this nasty hack once the test() template is
      # reworked.
      wait_for_openbox = False
      wait_openbox_program = './xwmstartupcheck'
      if not os.path.isfile(wait_openbox_program):
        wait_for_openbox = False
      # Creates a dummy window that waits for a ReparentNotify event that is
      # sent whenever Openbox WM starts. Must be started before the OpenBox WM
      # so that it does not miss the event. This helper program is located in
      # the current build directory. The program terminates automatically after
      # 30 seconds of waiting for the event.
      if wait_for_openbox:
        xwmstartupcheck_proc = subprocess.Popen(
            wait_openbox_program, stderr=subprocess.STDOUT, env=env)

      openbox_proc = subprocess.Popen(
          ['openbox', '--sm-disable'], stderr=subprocess.STDOUT, env=env)

      # Wait until execution is done. Does not block if the process has already
      # been terminated. In that case, it's safe to read the return value.
      if wait_for_openbox:
        xwmstartupcheck_proc.wait()
        if xwmstartupcheck_proc.returncode != 0:
          raise _XvfbProcessError('Failed to get OpenBox up.')

    if use_xcompmgr:
      xcompmgr_proc = subprocess.Popen(
          'xcompmgr', stderr=subprocess.STDOUT, env=env)

    return test_env.run_executable(cmd, env, stdoutfile)
  except OSError as e:
    print('Failed to start Xvfb or Openbox: %s\n' % str(e), file=sys.stderr)
    return 1
  except _XvfbProcessError as e:
    print('Xvfb fail: %s\n' % str(e), file=sys.stderr)
    return 1
  finally:
    kill(openbox_proc, 'openbox')
    kill(xcompmgr_proc, 'xcompmgr')
    kill(xvfb_proc, 'Xvfb')

    # dbus-daemon is not a subprocess, so we can't SIGTERM+waitpid() on it.
    # To ensure it exits, use SIGKILL which should be safe since all other
    # processes that it would have been servicing have exited.
    if dbus_pid:
      os.kill(dbus_pid, signal.SIGKILL)
def _run_with_xvfb(cmd, env, stdoutfile, use_openbox, use_xcompmgr):
  env['_CHROMIUM_INSIDE_XVFB'] = '1'
  openbox_proc = None
  xcompmgr_proc = None
  xvfb_proc = None
  xvfb_ready = MutableBoolean()
  def set_xvfb_ready(*_):
    xvfb_ready.setvalue(True)

  try:
    signal.signal(signal.SIGTERM, raise_xvfb_error)
    signal.signal(signal.SIGINT, raise_xvfb_error)

    # Due to race condition for display number, Xvfb might fail to run.
    # If it does fail, try again up to 10 times, similarly to xvfb-run.
    for _ in range(10):
      xvfb_ready.setvalue(False)
      display = find_display()

      # Sets SIGUSR1 to ignore for Xvfb to signal current process
      # when it is ready. Due to race condition, USR1 signal could be sent
      # before the process resets the signal handler, we cannot rely on
      # signal handler to change on time.
      signal.signal(signal.SIGUSR1, signal.SIG_IGN)
      xvfb_proc = subprocess.Popen(
          ['Xvfb', display, '-screen', '0', '1280x800x24', '-ac',
           '-nolisten', 'tcp', '-dpi', '96', '+extension', 'RANDR'],
          stderr=subprocess.STDOUT, env=env)
      signal.signal(signal.SIGUSR1, set_xvfb_ready)
      for _ in range(10):
        time.sleep(.1)  # gives Xvfb time to start or fail.
        if xvfb_ready.getvalue() or xvfb_proc.poll() is not None:
          break  # xvfb sent ready signal, or already failed and stopped.

      if xvfb_proc.poll() is None:
        break  # xvfb is running, can proceed.
    if xvfb_proc.poll() is not None:
      raise _XvfbProcessError('Failed to start after 10 tries')

    env['DISPLAY'] = display

    dbus_pid = launch_dbus(env)

    if use_openbox:
      openbox_proc = subprocess.Popen(
          'openbox', stderr=subprocess.STDOUT, env=env)

    if use_xcompmgr:
      xcompmgr_proc = subprocess.Popen(
          'xcompmgr', stderr=subprocess.STDOUT, env=env)

    return test_env.run_executable(cmd, env, stdoutfile)
  except OSError as e:
    print >> sys.stderr, 'Failed to start Xvfb or Openbox: %s' % str(e)
    return 1
  except _XvfbProcessError as e:
    print >> sys.stderr, 'Xvfb fail: %s' % str(e)
    return 1
  finally:
    kill(openbox_proc, 'openbox')
    kill(xcompmgr_proc, 'xcompmgr')
    kill(xvfb_proc, 'Xvfb')

    # dbus-daemon is not a subprocess, so we can't SIGTERM+waitpid() on it.
    # To ensure it exits, use SIGKILL which should be safe since all other
    # processes that it would have been servicing have exited.
    if dbus_pid:
      os.kill(dbus_pid, signal.SIGKILL)
示例#10
0
def _run_with_xvfb(cmd, env, stdoutfile, use_openbox, use_xcompmgr):
    env['_CHROMIUM_INSIDE_XVFB'] = '1'
    openbox_proc = None
    xcompmgr_proc = None
    xvfb_proc = None
    xwmstartupcheck_proc = None
    xvfb_ready = MutableBoolean()

    def set_xvfb_ready(*_):
        xvfb_ready.setvalue(True)

    try:
        signal.signal(signal.SIGTERM, raise_xvfb_error)
        signal.signal(signal.SIGINT, raise_xvfb_error)

        # Due to race condition for display number, Xvfb might fail to run.
        # If it does fail, try again up to 10 times, similarly to xvfb-run.
        for _ in range(10):
            xvfb_ready.setvalue(False)
            display = find_display()

            # Sets SIGUSR1 to ignore for Xvfb to signal current process
            # when it is ready. Due to race condition, USR1 signal could be sent
            # before the process resets the signal handler, we cannot rely on
            # signal handler to change on time.
            signal.signal(signal.SIGUSR1, signal.SIG_IGN)
            xvfb_proc = subprocess.Popen([
                'Xvfb', display, '-screen', '0', '1280x800x24', '-ac',
                '-nolisten', 'tcp', '-dpi', '96', '+extension', 'RANDR'
            ],
                                         stderr=subprocess.STDOUT,
                                         env=env)
            signal.signal(signal.SIGUSR1, set_xvfb_ready)
            for _ in range(10):
                time.sleep(.1)  # gives Xvfb time to start or fail.
                if xvfb_ready.getvalue() or xvfb_proc.poll() is not None:
                    break  # xvfb sent ready signal, or already failed and stopped.

            if xvfb_proc.poll() is None:
                break  # xvfb is running, can proceed.
        if xvfb_proc.poll() is not None:
            raise _XvfbProcessError('Failed to start after 10 tries')

        env['DISPLAY'] = display

        dbus_pid = launch_dbus(env)

        if use_openbox:
            # This is not ideal, but x11_unittests require that (other X11 tests have
            # a race with the openbox as well, but they take more time to initialize.
            # And thus, they do no time out compate to the x11_unittests that are
            # quick enough to start up before openbox is ready.
            # TODO(dpranke): remove this nasty hack once the test() template is
            # reworked.
            wait_for_openbox = False
            wait_openbox_program = './xwmstartupcheck'
            if not os.path.isfile(wait_openbox_program):
                wait_for_openbox = False
            # Creates a dummy window that waits for a ReparentNotify event that is
            # sent whenever Openbox WM starts. Must be started before the OpenBox WM
            # so that it does not miss the event. This helper program is located in
            # the current build directory. The program terminates automatically after
            # 30 seconds of waiting for the event.
            if wait_for_openbox:
                xwmstartupcheck_proc = subprocess.Popen(
                    wait_openbox_program, stderr=subprocess.STDOUT, env=env)

            openbox_proc = subprocess.Popen(['openbox', '--sm-disable'],
                                            stderr=subprocess.STDOUT,
                                            env=env)

            # Wait until execution is done. Does not block if the process has already
            # been terminated. In that case, it's safe to read the return value.
            if wait_for_openbox:
                xwmstartupcheck_proc.wait()
                if xwmstartupcheck_proc.returncode is not 0:
                    raise _XvfbProcessError('Failed to get OpenBox up.')

        if use_xcompmgr:
            xcompmgr_proc = subprocess.Popen('xcompmgr',
                                             stderr=subprocess.STDOUT,
                                             env=env)

        return test_env.run_executable(cmd, env, stdoutfile)
    except OSError as e:
        print('Failed to start Xvfb or Openbox: %s\n' % str(e),
              file=sys.stderr)
        return 1
    except _XvfbProcessError as e:
        print('Xvfb fail: %s\n' % str(e), file=sys.stderr)
        return 1
    finally:
        kill(openbox_proc, 'openbox')
        kill(xcompmgr_proc, 'xcompmgr')
        kill(xvfb_proc, 'Xvfb')

        # dbus-daemon is not a subprocess, so we can't SIGTERM+waitpid() on it.
        # To ensure it exits, use SIGKILL which should be safe since all other
        # processes that it would have been servicing have exited.
        if dbus_pid:
            os.kill(dbus_pid, signal.SIGKILL)
示例#11
0
def run_executable(cmd,
                   env,
                   stdoutfile=None,
                   use_openbox=True,
                   use_xcompmgr=True):
    """Runs an executable within Xvfb on Linux or normally on other platforms.

  The method sets SIGUSR1 handler for Xvfb to return SIGUSR1
  when it is ready for connections.
  https://www.x.org/archive/X11R7.5/doc/man/man1/Xserver.1.html under Signals.

  Args:
    cmd: Command to be executed.
    env: A copy of environment variables, "DISPLAY" and
      "_CHROMIUM_INSIDE_XVFB" will be set if Xvfb is used.
    stdoutfile: If provided, symbolization via script is disabled and stdout
      is written to this file as well as to stdout.
    use_openbox: A flag to use openbox process.
      Some ChromeOS tests need a window manager.
    use_xcompmgr: A flag to use xcompmgr process.
      Some tests need a compositing wm to make use of transparent visuals.

  Returns:
    the exit code of the specified commandline, or 1 on failure.
  """

    # It might seem counterintuitive to support a --no-xvfb flag in a script
    # whose only job is to start xvfb, but doing so allows us to consolidate
    # the logic in the layers of buildbot scripts so that we *always* use
    # xvfb by default and don't have to worry about the distinction, it
    # can remain solely under the control of the test invocation itself.
    use_xvfb = True
    if '--no-xvfb' in cmd:
        use_xvfb = False
        cmd.remove('--no-xvfb')

    if sys.platform == 'linux2' and use_xvfb:
        env['_CHROMIUM_INSIDE_XVFB'] = '1'
        openbox_proc = None
        xcompmgr_proc = None
        xvfb_proc = None
        xvfb_ready = MutableBoolean()

        def set_xvfb_ready(*_):
            xvfb_ready.setvalue(True)

        try:
            signal.signal(signal.SIGTERM, raise_xvfb_error)
            signal.signal(signal.SIGINT, raise_xvfb_error)

            # Due to race condition for display number, Xvfb might fail to run.
            # If it does fail, try again up to 10 times, similarly to xvfb-run.
            for _ in range(10):
                xvfb_ready.setvalue(False)
                display = find_display()

                # Sets SIGUSR1 to ignore for Xvfb to signal current process
                # when it is ready. Due to race condition, USR1 signal could be sent
                # before the process resets the signal handler, we cannot rely on
                # signal handler to change on time.
                signal.signal(signal.SIGUSR1, signal.SIG_IGN)
                xvfb_proc = subprocess.Popen([
                    'Xvfb', display, '-screen', '0', '1280x800x24', '-ac',
                    '-nolisten', 'tcp', '-dpi', '96', '+extension', 'RANDR'
                ],
                                             stderr=subprocess.STDOUT,
                                             env=env)
                signal.signal(signal.SIGUSR1, set_xvfb_ready)
                for _ in range(10):
                    time.sleep(.1)  # gives Xvfb time to start or fail.
                    if xvfb_ready.getvalue() or xvfb_proc.poll() is not None:
                        break  # xvfb sent ready signal, or already failed and stopped.

                if xvfb_proc.poll() is None:
                    break  # xvfb is running, can proceed.
            if xvfb_proc.poll() is not None:
                raise _XvfbProcessError('Failed to start after 10 tries')

            env['DISPLAY'] = display

            if use_openbox:
                openbox_proc = subprocess.Popen('openbox',
                                                stderr=subprocess.STDOUT,
                                                env=env)

            if use_xcompmgr:
                xcompmgr_proc = subprocess.Popen('xcompmgr',
                                                 stderr=subprocess.STDOUT,
                                                 env=env)

            return test_env.run_executable(cmd, env, stdoutfile)
        except OSError as e:
            print >> sys.stderr, 'Failed to start Xvfb or Openbox: %s' % str(e)
            return 1
        except _XvfbProcessError as e:
            print >> sys.stderr, 'Xvfb fail: %s' % str(e)
            return 1
        finally:
            kill(openbox_proc)
            kill(xcompmgr_proc)
            kill(xvfb_proc)
    else:
        return test_env.run_executable(cmd, env, stdoutfile)