Chromium Code Reviews| Index: build/android/pylib/forwarder.py |
| diff --git a/build/android/pylib/forwarder.py b/build/android/pylib/forwarder.py |
| index 03b16f17a84b487d2c41a025bcecdc9aaa607d4d..a29a6d96088267f58cafc33c65b656ffee03e198 100644 |
| --- a/build/android/pylib/forwarder.py |
| +++ b/build/android/pylib/forwarder.py |
| @@ -9,12 +9,17 @@ import re |
| import sys |
| import android_commands |
| +import cmd_helper |
| import constants |
| +import ports |
| class Forwarder(object): |
| """Class to manage port forwards from the device to the host.""" |
| - _FORWARDER_PATH = constants.TEST_EXECUTABLE_DIR + '/forwarder' |
| + _DEVICE_FORWARDER_PATH = constants.TEST_EXECUTABLE_DIR + '/device_forwarder' |
| + |
| + # Unix Abstract socket path: |
| + _DEVICE_ADB_CONTROL_PORT = 'chrome_device_forwarder' |
| _TIMEOUT_SECS = 30 |
| def __init__(self, adb, port_pairs, tool, host_name, build_type): |
| @@ -40,67 +45,125 @@ class Forwarder(object): |
| """ |
| self._adb = adb |
| self._host_to_device_port_map = dict() |
| - self._process = None |
| + self._host_process = None |
| + self._device_process = None |
| + self._adb_forward_process = None |
| + |
| + self._host_adb_control_port = ports.AllocateTestServerPort() |
| adb.PushIfNeeded( |
| - os.path.join(constants.CHROME_DIR, 'out', build_type, 'forwarder'), |
| - Forwarder._FORWARDER_PATH) |
| + os.path.join(constants.CHROME_DIR, 'out', build_type, |
| + 'device_forwarder'), |
| + Forwarder._DEVICE_FORWARDER_PATH) |
| + self._host_forwarder_path = os.path.join(constants.CHROME_DIR, |
| + 'out', |
| + build_type, |
| + 'host_forwarder') |
| forward_string = ['%d:%d:%s' % |
| (device, host, host_name) for device, host in port_pairs] |
| - |
| - # Kill off any existing forwarders on conflicting non-dynamically allocated |
| - # ports. |
| + logging.info('Forwarding ports: %s' % (forward_string)) |
|
bulach
2012/09/26 15:13:11
logging takes a format and vararg as well, so this
felipeg
2012/09/26 18:06:03
Done.
|
| + # Kill off any existing device forwarders on conflicting non-dynamically |
| + # allocated ports. |
| for device_port, _ in port_pairs: |
| if device_port != 0: |
| self._KillForwardersUsingDevicePort(device_port) |
| - logging.info('Forwarding ports: %s' % (forward_string)) |
| - process = pexpect.spawn( |
| - 'adb', ['-s', adb._adb.GetSerialNumber(), |
| - 'shell', '%s %s -D %s' % ( |
| - tool.GetUtilWrapper(), Forwarder._FORWARDER_PATH, |
| - ' '.join(forward_string))]) |
| + # Kill any existing host forwarders. |
| + cmd_helper.RunCmd(['killall', 'host_forwarder']) |
| + self._adb_forward_process = pexpect.spawn( |
| + 'adb', ['-s', |
| + adb._adb.GetSerialNumber(), |
| + 'forward', |
| + 'tcp:%s' % self._host_adb_control_port, |
| + 'localabstract:%s' % Forwarder._DEVICE_ADB_CONTROL_PORT]) |
| + self._device_process = pexpect.spawn( |
| + 'adb', ['-s', |
| + adb._adb.GetSerialNumber(), |
| + 'shell', |
| + '%s %s -D --adb_sock=%s' % ( |
| + tool.GetUtilWrapper(), |
| + Forwarder._DEVICE_FORWARDER_PATH, |
| + Forwarder._DEVICE_ADB_CONTROL_PORT)]) |
| + |
| + device_success_re = re.compile('Starting Device Forwarder.') |
| + device_failure_re = re.compile('.*:ERROR:(.*)') |
| + index = self._device_process.expect([device_success_re, |
| + device_failure_re, |
| + pexpect.EOF, |
| + pexpect.TIMEOUT], |
| + Forwarder._TIMEOUT_SECS) |
| + if index == 1: |
| + # Failure |
| + error_msg = str(self._device_process.match.group(1)) |
| + logging.error(self._device_process.before) |
| + self._CloseProcess() |
| + raise Exception('Failed to start Device Forwarder with Error: %s' % ( |
| + error_msg)) |
|
bulach
2012/09/26 15:13:11
nit: no need for the extra parens around error_msg
felipeg
2012/09/26 18:06:03
Done.
|
| + elif index == 2: |
| + logging.error(self._device_process.before) |
| + self._CloseProcess() |
| + raise Exception('Unexpected EOF while trying to start Device Forwarder.') |
| + elif index == 3: |
| + logging.error(self._device_process.before) |
| + self._CloseProcess() |
| + raise Exception('Timeout while trying start Device Forwarder') |
| + |
| + self._host_process = pexpect.spawn(self._host_forwarder_path, |
| + ['--adb_port=%s' % ( |
| + self._host_adb_control_port), |
| + ' '.join(forward_string)]) |
| # Read the output of the command to determine which device ports where |
| # forwarded to which host ports (necessary if |
| - success_re = re.compile('Forwarding device port (\d+) to host (\d+):') |
| - failure_re = re.compile('Couldn\'t start forwarder server for port spec: ' |
| - '(\d+):(\d+)') |
| + host_success_re = re.compile('Forwarding device port (\d+) to host (\d+):') |
| + host_failure_re = re.compile('Couldn\'t start forwarder server for port ' |
| + 'spec: (\d+):(\d+)') |
| for pair in port_pairs: |
| - index = process.expect([success_re, failure_re, pexpect.EOF, |
| - pexpect.TIMEOUT], |
| - Forwarder._TIMEOUT_SECS) |
| + index = self._host_process.expect([host_success_re, |
| + host_failure_re, |
| + pexpect.EOF, |
| + pexpect.TIMEOUT], |
| + Forwarder._TIMEOUT_SECS) |
| if index == 0: |
| # Success |
| - device_port = int(process.match.group(1)) |
| - host_port = int(process.match.group(2)) |
| + device_port = int(self._host_process.match.group(1)) |
| + host_port = int(self._host_process.match.group(2)) |
| self._host_to_device_port_map[host_port] = device_port |
| logging.info("Forwarding device port: %d to host port: %d." % |
| (device_port, host_port)) |
| elif index == 1: |
| # Failure |
| - device_port = int(process.match.group(1)) |
| - host_port = int(process.match.group(2)) |
| - process.close() |
| + device_port = int(self._host_process.match.group(1)) |
| + host_port = int(self._host_process.match.group(2)) |
| + self._CloseProcess() |
| raise Exception('Failed to forward port %d to %d' % (device_port, |
| host_port)) |
| elif index == 2: |
| - logging.error(process.before) |
| - process.close() |
| + logging.error(self._host_process.before) |
| + self._CloseProcess() |
| raise Exception('Unexpected EOF while trying to forward ports %s' % |
| port_pairs) |
| elif index == 3: |
| - logging.error(process.before) |
| - process.close() |
| + logging.error(self._host_process.before) |
| + self._CloseProcess() |
| raise Exception('Timeout while trying to forward ports %s' % port_pairs) |
| - self._process = process |
| + def _CloseProcess(self): |
| + if self._host_process: |
| + self._host_process.close() |
| + if self._device_process: |
| + self._device_process.close() |
| + if self._adb_forward_process: |
| + self._adb_forward_process.close() |
| + self._host_process = None |
| + self._device_process = None |
| + self._adb_forward_process = None |
| def _KillForwardersUsingDevicePort(self, device_port): |
| """Check if the device port is in use and if it is try to terminate the |
| forwarder process (if any) that may already be forwarding it""" |
| processes = self._adb.ProcessesUsingDevicePort(device_port) |
| for pid, name in processes: |
| - if name == 'forwarder': |
| + if name == 'device_forwarder': |
| logging.warning( |
| 'Killing forwarder process with pid %d using device_port %d' % ( |
| pid, device_port)) |
| @@ -116,6 +179,4 @@ class Forwarder(object): |
| def Close(self): |
| """Terminate the forwarder process.""" |
| - if self._process: |
| - self._process.close() |
| - self._process = None |
| + self._CloseProcess() |