xvfb.py revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1# Copyright (c) 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import os
6import signal
7import subprocess
8import sys
9import time
10
11
12def _IsLinux():
13  """Return True if on Linux; else False."""
14  return sys.platform.startswith('linux')
15
16
17class Xvfb(object):
18  """Class to start and stop Xvfb if relevant.  Nop if not Linux."""
19
20  def __init__(self):
21    self._pid = 0
22
23  def Start(self):
24    """Start Xvfb and set an appropriate DISPLAY environment.  Linux only.
25
26    Copied from tools/code_coverage/coverage_posix.py
27    """
28    if not _IsLinux():
29      return
30    proc = subprocess.Popen(['Xvfb', ':9', '-screen', '0', '1024x768x24',
31                             '-ac'],
32                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
33    self._pid = proc.pid
34    if not self._pid:
35      raise Exception('Could not start Xvfb')
36    os.environ['DISPLAY'] = ':9'
37
38    # Now confirm, giving a chance for it to start if needed.
39    for _ in range(10):
40      proc = subprocess.Popen('xdpyinfo >/dev/null', shell=True)
41      _, retcode = os.waitpid(proc.pid, 0)
42      if retcode == 0:
43        break
44      time.sleep(0.25)
45    if retcode != 0:
46      raise Exception('Could not confirm Xvfb happiness')
47
48  def Stop(self):
49    """Stop Xvfb if needed.  Linux only."""
50    if self._pid:
51      try:
52        os.kill(self._pid, signal.SIGKILL)
53      except:
54        pass
55      del os.environ['DISPLAY']
56      self._pid = 0
57