|  | #!/usr/bin/env python | 
|  | # Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | import os | 
|  | import re | 
|  | import subprocess | 
|  | import sys | 
|  |  | 
|  | from gpu_tests import path_util | 
|  |  | 
|  | path_util.SetupTelemetryPaths() | 
|  |  | 
|  | from telemetry import benchmark_runner | 
|  |  | 
|  | import gpu_project_config | 
|  |  | 
|  |  | 
|  | def _LaunchDBus(): | 
|  | """Launches DBus to work around a bug in GLib. | 
|  |  | 
|  | Works around a bug in GLib where it performs operations which aren't | 
|  | async-signal-safe (in particular, memory allocations) between fork and exec | 
|  | when it spawns subprocesses. This causes threads inside Chrome's browser and | 
|  | utility processes to get stuck, and this harness to hang waiting for those | 
|  | processes, which will never terminate. This doesn't happen on users' | 
|  | machines, because they have an active desktop session and the | 
|  | DBUS_SESSION_BUS_ADDRESS environment variable set, but it does happen on the | 
|  | bots. See crbug.com/309093 for more details. | 
|  |  | 
|  | Returns: | 
|  | True if it actually spawned DBus. | 
|  | """ | 
|  | import platform | 
|  | if (platform.uname()[0].lower() != 'linux' or | 
|  | 'DBUS_SESSION_BUS_ADDRESS' in os.environ): | 
|  | return False | 
|  |  | 
|  | # Only start DBus on systems that are actually running X. Using DISPLAY | 
|  | # variable is not reliable, because is it set by the /etc/init.d/buildbot | 
|  | # script for all slaves. | 
|  | # TODO(sergiyb): When all GPU slaves are migrated to swarming, we can remove | 
|  | # assignment of the DISPLAY from /etc/init.d/buildbot because this hack was | 
|  | # used to run GPU tests on buildbot. After it is removed, we can use DISPLAY | 
|  | # variable here to check if we are running X. | 
|  | if subprocess.call(['pidof', 'X'], stdout=subprocess.PIPE) == 0: | 
|  | try: | 
|  | print 'DBUS_SESSION_BUS_ADDRESS env var not found, starting dbus-launch' | 
|  | dbus_output = subprocess.check_output(['dbus-launch']).split('\n') | 
|  | for line in dbus_output: | 
|  | m = re.match(r'([^=]+)\=(.+)', line) | 
|  | if m: | 
|  | os.environ[m.group(1)] = m.group(2) | 
|  | print ' setting %s to %s' % (m.group(1), m.group(2)) | 
|  | return True | 
|  | except (subprocess.CalledProcessError, OSError) as e: | 
|  | print 'Exception while running dbus_launch: %s' % e | 
|  | return False | 
|  |  | 
|  |  | 
|  | def _ShutdownDBus(): | 
|  | """Manually kills the previously-launched DBus daemon. | 
|  |  | 
|  | It appears that passing --exit-with-session to dbus-launch in | 
|  | _LaunchDBus(), above, doesn't cause the launched dbus-daemon to shut | 
|  | down properly. Manually kill the sub-process using the PID it gave | 
|  | us at launch time. | 
|  |  | 
|  | This function is called when the flag --spawn-dbus is given, and if | 
|  | _LaunchDBus(), above, actually spawned the dbus-daemon. | 
|  | """ | 
|  | import signal | 
|  | if 'DBUS_SESSION_BUS_PID' in os.environ: | 
|  | dbus_pid = os.environ['DBUS_SESSION_BUS_PID'] | 
|  | try: | 
|  | os.kill(int(dbus_pid), signal.SIGTERM) | 
|  | print ' killed dbus-daemon with PID %s' % dbus_pid | 
|  | except OSError as e: | 
|  | print ' error killing dbus-daemon with PID %s: %s' % (dbus_pid, e) | 
|  | # Try to clean up any stray DBUS_SESSION_BUS_ADDRESS environment | 
|  | # variable too. Some of the bots seem to re-invoke runtest.py in a | 
|  | # way that this variable sticks around from run to run. | 
|  | if 'DBUS_SESSION_BUS_ADDRESS' in os.environ: | 
|  | del os.environ['DBUS_SESSION_BUS_ADDRESS'] | 
|  | print ' cleared DBUS_SESSION_BUS_ADDRESS environment variable' | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | did_launch_dbus = _LaunchDBus() | 
|  | try: | 
|  | retcode = benchmark_runner.main(gpu_project_config.CONFIG) | 
|  | finally: | 
|  | if did_launch_dbus: | 
|  | _ShutdownDBus() | 
|  |  | 
|  | sys.exit(retcode) |