Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: build/android/pylib/forwarder.py

Issue 15151003: Use a single Python Forwarder instance for each base test runner instance. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Craig + Frank comments Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/android/pylib/chrome_test_server_spawner.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/android/pylib/forwarder.py
diff --git a/build/android/pylib/forwarder.py b/build/android/pylib/forwarder.py
index f5cde9e29da230201fa3c4ec48408c8319f5cb3c..965823ee4dace1d0e3a33e64ecb95220771e9d24 100644
--- a/build/android/pylib/forwarder.py
+++ b/build/android/pylib/forwarder.py
@@ -6,6 +6,7 @@ import logging
import os
import re
import sys
+import threading
import time
import android_commands
@@ -21,7 +22,7 @@ def _MakeBinaryPath(build_type, binary_name):
class Forwarder(object):
- """Class to manage port forwards from the device to the host."""
+ """Thread-safe class to manage port forwards from the device to the host."""
# Unix Abstract socket path:
_DEVICE_ADB_CONTROL_PORT = 'chrome_device_forwarder'
@@ -45,7 +46,9 @@ class Forwarder(object):
assert build_type in ('Release', 'Debug')
self._adb = adb
self._host_to_device_port_map = dict()
- self._device_process = None
+ self._device_initialized = False
+ self._host_adb_control_port = 0
+ self._lock = threading.Lock()
self._host_forwarder_path = _MakeBinaryPath(build_type, 'host_forwarder')
self._device_forwarder_path_on_host = os.path.join(
cmd_helper.OutDirectory.get(), build_type, 'forwarder_dist')
@@ -67,23 +70,58 @@ class Forwarder(object):
Raises:
Exception on failure to forward the port.
"""
+ with self._lock:
+ self._InitDeviceLocked(tool)
+ self._InitHostLocked()
+ redirection_commands = [
+ '%d:%d:%d:%s' % (self._host_adb_control_port, device, host,
+ host_name) for device, host in port_pairs]
+ logging.info('Command format: <ADB port>:<Device port>' +
+ '[:<Forward to port>:<Forward to address>]')
+ logging.info('Forwarding using commands: %s', redirection_commands)
+
+ for redirection_command in redirection_commands:
+ try:
+ (exit_code, output) = cmd_helper.GetCmdStatusAndOutput(
+ [self._host_forwarder_path, redirection_command])
+ except OSError as e:
+ if e.errno == 2:
+ raise Exception('Unable to start host forwarder. Make sure you have'
+ ' built host_forwarder.')
+ else: raise
+ if exit_code != 0:
+ raise Exception('%s exited with %d:\n%s' % (
+ self._host_forwarder_path, exit_code, '\n'.join(output)))
+ tokens = output.split(':')
+ if len(tokens) != 2:
+ raise Exception('Unexpected host forwarder output "%s", ' +
+ 'expected "device_port:host_port"' % output)
+ device_port = int(tokens[0])
+ host_port = int(tokens[1])
+ self._host_to_device_port_map[host_port] = device_port
+ logging.info('Forwarding device port: %d to host port: %d.',
+ device_port, host_port)
+
+ def _InitHostLocked(self):
+ """Initializes the host forwarder process (only once)."""
+ if self._host_adb_control_port:
+ return
self._host_adb_control_port = ports.AllocateTestServerPort()
if not self._host_adb_control_port:
raise Exception('Failed to allocate a TCP port in the host machine.')
- self._adb.PushIfNeeded(
- self._device_forwarder_path_on_host, Forwarder._DEVICE_FORWARDER_FOLDER)
- redirection_commands = [
- '%d:%d:%d:%s' % (self._host_adb_control_port, device, host,
- host_name) for device, host in port_pairs]
- logging.info('Command format: <ADB port>:<Device port>' +
- '[:<Forward to port>:<Forward to address>]')
- logging.info('Forwarding using commands: %s', redirection_commands)
if cmd_helper.RunCmd(
['adb', '-s', self._adb._adb.GetSerialNumber(), 'forward',
'tcp:%s' % self._host_adb_control_port,
'localabstract:%s' % Forwarder._DEVICE_ADB_CONTROL_PORT]) != 0:
raise Exception('Error while running adb forward.')
+ def _InitDeviceLocked(self, tool):
+ """Initializes the device forwarder process (only once)."""
+ if self._device_initialized:
+ return
+ self._adb.PushIfNeeded(
+ self._device_forwarder_path_on_host,
+ Forwarder._DEVICE_FORWARDER_FOLDER)
(exit_code, output) = self._adb.GetShellCommandStatusAndOutput(
'%s %s %s %s' % (Forwarder._LD_LIBRARY_PATH, tool.GetUtilWrapper(),
Forwarder._DEVICE_FORWARDER_PATH,
@@ -91,40 +129,31 @@ class Forwarder(object):
if exit_code != 0:
raise Exception(
'Failed to start device forwarder:\n%s' % '\n'.join(output))
+ self._device_initialized = True
+
+ def UnmapDevicePort(self, device_port):
+ """Unmaps a previously forwarded device port.
- for redirection_command in redirection_commands:
- try:
- (exit_code, output) = cmd_helper.GetCmdStatusAndOutput(
- [self._host_forwarder_path, redirection_command])
- except OSError as e:
- if e.errno == 2:
- raise Exception('Unable to start host forwarder. Make sure you have '
- 'built host_forwarder.')
- else: raise
+ Args:
+ device_port: A previously forwarded port (through Run()).
+ """
+ with self._lock:
+ # Please note the minus sign below.
+ redirection_command = '%d:-%d' % (
+ self._host_adb_control_port, device_port)
+ (exit_code, output) = cmd_helper.GetCmdStatusAndOutput(
+ [self._host_forwarder_path, redirection_command])
if exit_code != 0:
raise Exception('%s exited with %d:\n%s' % (
self._host_forwarder_path, exit_code, '\n'.join(output)))
- tokens = output.split(':')
- if len(tokens) != 2:
- raise Exception('Unexpected host forwarder output "%s", ' +
- 'expected "device_port:host_port"' % output)
- device_port = int(tokens[0])
- host_port = int(tokens[1])
- self._host_to_device_port_map[host_port] = device_port
- logging.info('Forwarding device port: %d to host port: %d.', device_port,
- host_port)
-
- def UnmapDevicePort(self, device_port):
- # Please note the minus sign below.
- redirection_command = '%d:-%d' % (self._host_adb_control_port, device_port)
- (exit_code, output) = cmd_helper.GetCmdStatusAndOutput(
- [self._host_forwarder_path, redirection_command])
- if exit_code != 0:
- raise Exception('%s exited with %d:\n%s' % (
- self._host_forwarder_path, exit_code, '\n'.join(output)))
@staticmethod
def KillHost(build_type):
+ """Kills the forwarder process running on the host.
+
+ Args:
+ build_type: 'Release' or 'Debug'
+ """
logging.info('Killing host_forwarder.')
host_forwarder_path = _MakeBinaryPath(build_type, 'host_forwarder')
assert os.path.exists(host_forwarder_path), 'Please build forwarder2'
@@ -139,6 +168,13 @@ class Forwarder(object):
@staticmethod
def KillDevice(adb, tool):
+ """Kills the forwarder process running on the device.
+
+ Args:
+ adb: Instance of AndroidCommands for talking to the device.
+ tool: Wrapper tool (e.g. valgrind) that can be used to execute the device
+ forwarder (see valgrind_tools.py).
+ """
logging.info('Killing device_forwarder.')
if not adb.FileExistsOnDevice(Forwarder._DEVICE_FORWARDER_PATH):
return
@@ -156,11 +192,12 @@ class Forwarder(object):
raise Exception('Timed out while killing device_forwarder')
def DevicePortForHostPort(self, host_port):
- """Get the device port that corresponds to a given host port."""
- return self._host_to_device_port_map.get(host_port)
+ """Returns the device port that corresponds to a given host port."""
+ with self._lock:
+ return self._host_to_device_port_map.get(host_port)
+ # Deprecated.
def Close(self):
- """Terminate the forwarder process."""
- if self._device_process:
- self._device_process.close()
- self._device_process = None
+ """Terminates the forwarder process."""
+ # TODO(pliard): Remove references in client code.
+ pass
« no previous file with comments | « build/android/pylib/chrome_test_server_spawner.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698