Flutter Engine
The Flutter Engine
xvfb.py
Go to the documentation of this file.
1# Copyright (c) 2012 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"""Functions to setup xvfb, which is used by the linux machines.
6"""
7
8import os
9import signal
10import subprocess
11import tempfile
12import time
13
14
15def xvfb_display_index(_child_build_name):
16 return '9'
17
18
19def xvfb_pid_filename(child_build_name):
20 """Returns the filename to the Xvfb pid file. This name is unique for each
21 builder. This is used by the linux builders."""
22 return os.path.join(
23 tempfile.gettempdir(), 'xvfb-' + xvfb_display_index(child_build_name) + '.pid'
24 )
25
26
27def start_virtual_x(child_build_name, build_dir):
28 """Start a virtual X server and set the DISPLAY environment variable so sub
29 processes will use the virtual X server. Also start openbox. This only works
30 on Linux and assumes that xvfb and openbox are installed.
31
32 Args:
33 child_build_name: The name of the build that we use for the pid file.
34 E.g., webkit-rel-linux.
35 build_dir: The directory where binaries are produced. If this is non-empty,
36 we try running xdisplaycheck from |build_dir| to verify our X
37 connection.
38 """
39 # We use a pid file to make sure we don't have any xvfb processes running
40 # from a previous test run.
41 stop_virtual_x(child_build_name)
42
43 xdisplaycheck_path = None
44 if build_dir:
45 xdisplaycheck_path = os.path.join(build_dir, 'xdisplaycheck')
46
47 display = ':%s' % xvfb_display_index(child_build_name)
48 # Note we don't add the optional screen here (+ '.0')
49 os.environ['DISPLAY'] = display
50
51 # Parts of Xvfb use a hard-coded "/tmp" for its temporary directory.
52 # This can cause a failure when those parts expect to hardlink against
53 # files that were created in "TEMPDIR" / "TMPDIR".
54 #
55 # See: https://crbug.com/715848
56 env = os.environ.copy()
57 if env.get('TMPDIR') and env['TMPDIR'] != '/tmp':
58 print('Overriding TMPDIR to "/tmp" for Xvfb, was: %s' % (env['TMPDIR'],))
59 env['TMPDIR'] = '/tmp'
60
61 if xdisplaycheck_path and os.path.exists(xdisplaycheck_path):
62 print('Verifying Xvfb is not running ...')
63 checkstarttime = time.time()
64 xdisplayproc = subprocess.Popen([xdisplaycheck_path, '--noserver'],
65 stdout=subprocess.PIPE,
66 stderr=subprocess.STDOUT,
67 env=env)
68 # Wait for xdisplaycheck to exit.
69 logs = xdisplayproc.communicate()[0]
70 if xdisplayproc.returncode == 0:
71 print('xdisplaycheck says there is a display still running, exiting...')
72 raise Exception('Display already present.')
73
74 xvfb_lock_filename = '/tmp/.X%s-lock' % xvfb_display_index(child_build_name)
75 if os.path.exists(xvfb_lock_filename):
76 print('Removing stale xvfb lock file %r' % xvfb_lock_filename)
77 try:
78 os.unlink(xvfb_lock_filename)
79 except OSError as err:
80 print('Removing xvfb lock file failed: %s' % err)
81
82 # Figure out which X server to try.
83 cmd = 'Xvfb'
84
85 # Start a virtual X server that we run the tests in. This makes it so we can
86 # run the tests even if we didn't start the tests from an X session.
87 proc = subprocess.Popen([
88 cmd, display, '-screen', '0', '1280x800x24', '-ac', '-dpi', '96', '-maxclients', '512',
89 '-extension', 'MIT-SHM'
90 ],
91 stdout=subprocess.PIPE,
92 stderr=subprocess.STDOUT,
93 env=env)
94 pid_filename = xvfb_pid_filename(child_build_name)
95 open(pid_filename, 'w').write(str(proc.pid))
96
97 # Wait for Xvfb to start up.
98 time.sleep(10)
99
100 # Verify that Xvfb has started by using xdisplaycheck.
101 if xdisplaycheck_path and os.path.exists(xdisplaycheck_path):
102 print('Verifying Xvfb has started...')
103 checkstarttime = time.time()
104 xdisplayproc = subprocess.Popen([xdisplaycheck_path],
105 stdout=subprocess.PIPE,
106 stderr=subprocess.STDOUT)
107 # Wait for xdisplaycheck to exit.
108 logs = xdisplayproc.communicate()[0]
109 checktime = time.time() - checkstarttime
110 if xdisplayproc.returncode != 0:
111 print('xdisplaycheck failed after %d seconds.' % checktime)
112 print('xdisplaycheck output:')
113 for line in logs.splitlines():
114 print('> %s' % line)
115 return_code = proc.poll()
116 if return_code is None:
117 print('Xvfb still running, stopping.')
118 proc.terminate()
119 else:
120 print('Xvfb exited, code %d' % return_code)
121
122 print('Xvfb output:')
123 for line in proc.communicate()[0].splitlines():
124 print('> %s' % line)
125 raise Exception(logs)
126
127 print('xdisplaycheck succeeded after %d seconds.' % checktime)
128 print('xdisplaycheck output:')
129 for line in logs.splitlines():
130 print('> %s' % line)
131 print('...OK')
132
133 # Some ChromeOS tests need a window manager.
134 subprocess.Popen('openbox', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
135 print('Window manager (openbox) started.')
136
137
138def stop_virtual_x(child_build_name):
139 """Try and stop the virtual X server if one was started with StartVirtualX.
140 When the X server dies, it takes down the window manager with it.
141 If a virtual x server is not running, this method does nothing."""
142 pid_filename = xvfb_pid_filename(child_build_name)
143 if os.path.exists(pid_filename):
144 xvfb_pid = int(open(pid_filename).read())
145 print('Stopping Xvfb with pid %d ...' % xvfb_pid)
146 # If the process doesn't exist, we raise an exception that we can ignore.
147 try:
148 os.kill(xvfb_pid, signal.SIGKILL)
149 except OSError:
150 print('... killing failed, presuming unnecessary.')
151 os.remove(pid_filename)
152 print('Xvfb pid file removed')
static bool read(SkStream *stream, void *buffer, size_t amount)
def print(*args, **kwargs)
Definition: run_tests.py:49
def xvfb_pid_filename(child_build_name)
Definition: xvfb.py:19
def xvfb_display_index(_child_build_name)
Definition: xvfb.py:15
def start_virtual_x(child_build_name, build_dir)
Definition: xvfb.py:27
def stop_virtual_x(child_build_name)
Definition: xvfb.py:138
void write(SkWStream *wStream, const T &text)
Definition: skqp.cpp:188