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
5# pylint: disable=W0702
6
7import os
8import signal
9import subprocess
10import sys
11import time
12
13
14def _IsLinux():
15  """Return True if on Linux; else False."""
16  return sys.platform.startswith('linux')
17
18
19class Xvfb(object):
20  """Class to start and stop Xvfb if relevant.  Nop if not Linux."""
21
22  def __init__(self):
23    self._pid = 0
24
25  def Start(self):
26    """Start Xvfb and set an appropriate DISPLAY environment.  Linux only.
27
28    Copied from tools/code_coverage/coverage_posix.py
29    """
30    if not _IsLinux():
31      return
32    proc = subprocess.Popen(['Xvfb', ':9', '-screen', '0', '1024x768x24',
33                             '-ac'],
34                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
35    self._pid = proc.pid
36    if not self._pid:
37      raise Exception('Could not start Xvfb')
38    os.environ['DISPLAY'] = ':9'
39
40    # Now confirm, giving a chance for it to start if needed.
41    for _ in range(10):
42      proc = subprocess.Popen('xdpyinfo >/dev/null', shell=True)
43      _, retcode = os.waitpid(proc.pid, 0)
44      if retcode == 0:
45        break
46      time.sleep(0.25)
47    if retcode != 0:
48      raise Exception('Could not confirm Xvfb happiness')
49
50  def Stop(self):
51    """Stop Xvfb if needed.  Linux only."""
52    if self._pid:
53      try:
54        os.kill(self._pid, signal.SIGKILL)
55      except:
56        pass
57      del os.environ['DISPLAY']
58      self._pid = 0
59