| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 # pylint: disable=W0212 | |
| 6 | |
| 7 import fcntl | 5 import fcntl |
| 8 import logging | 6 import logging |
| 9 import os | 7 import os |
| 10 import psutil | 8 import psutil |
| 9 import re |
| 10 import sys |
| 11 import time |
| 11 | 12 |
| 12 from pylib import cmd_helper | 13 import android_commands |
| 13 from pylib import constants | 14 import cmd_helper |
| 15 import constants |
| 16 |
| 14 from pylib import valgrind_tools | 17 from pylib import valgrind_tools |
| 15 | 18 |
| 16 | 19 |
| 17 def _GetProcessStartTime(pid): | 20 def _GetProcessStartTime(pid): |
| 18 return psutil.Process(pid).create_time | 21 return psutil.Process(pid).create_time |
| 19 | 22 |
| 20 | 23 |
| 21 class _FileLock(object): | 24 class _FileLock(object): |
| 22 """With statement-aware implementation of a file lock. | 25 """With statement-aware implementation of a file lock. |
| 23 | 26 |
| 24 File locks are needed for cross-process synchronization when the | 27 File locks are needed for cross-process synchronization when the |
| 25 multiprocessing Python module is used. | 28 multiprocessing Python module is used. |
| 26 """ | 29 """ |
| 27 def __init__(self, path): | 30 def __init__(self, path): |
| 28 self._fd = -1 | |
| 29 self._path = path | 31 self._path = path |
| 30 | 32 |
| 31 def __enter__(self): | 33 def __enter__(self): |
| 32 self._fd = os.open(self._path, os.O_RDONLY | os.O_CREAT) | 34 self._fd = os.open(self._path, os.O_RDONLY | os.O_CREAT) |
| 33 if self._fd < 0: | 35 if self._fd < 0: |
| 34 raise Exception('Could not open file %s for reading' % self._path) | 36 raise Exception('Could not open file %s for reading' % self._path) |
| 35 fcntl.flock(self._fd, fcntl.LOCK_EX) | 37 fcntl.flock(self._fd, fcntl.LOCK_EX) |
| 36 | 38 |
| 37 def __exit__(self, _exception_type, _exception_value, traceback): | 39 def __exit__(self, type, value, traceback): |
| 38 fcntl.flock(self._fd, fcntl.LOCK_UN) | 40 fcntl.flock(self._fd, fcntl.LOCK_UN) |
| 39 os.close(self._fd) | 41 os.close(self._fd) |
| 40 | 42 |
| 41 | 43 |
| 42 class Forwarder(object): | 44 class Forwarder(object): |
| 43 """Thread-safe class to manage port forwards from the device to the host.""" | 45 """Thread-safe class to manage port forwards from the device to the host.""" |
| 44 | 46 |
| 45 _DEVICE_FORWARDER_FOLDER = (constants.TEST_EXECUTABLE_DIR + | 47 _DEVICE_FORWARDER_FOLDER = (constants.TEST_EXECUTABLE_DIR + |
| 46 '/forwarder/') | 48 '/forwarder/') |
| 47 _DEVICE_FORWARDER_PATH = (constants.TEST_EXECUTABLE_DIR + | 49 _DEVICE_FORWARDER_PATH = (constants.TEST_EXECUTABLE_DIR + |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 # There are no more ports mapped, kill the device_forwarder. | 147 # There are no more ports mapped, kill the device_forwarder. |
| 146 tool = valgrind_tools.CreateTool(None, adb) | 148 tool = valgrind_tools.CreateTool(None, adb) |
| 147 Forwarder._KillDeviceLocked(adb, tool) | 149 Forwarder._KillDeviceLocked(adb, tool) |
| 148 Forwarder._instance._initialized_devices.remove(adb_serial) | 150 Forwarder._instance._initialized_devices.remove(adb_serial) |
| 149 | 151 |
| 150 | 152 |
| 151 @staticmethod | 153 @staticmethod |
| 152 def DevicePortForHostPort(host_port): | 154 def DevicePortForHostPort(host_port): |
| 153 """Returns the device port that corresponds to a given host port.""" | 155 """Returns the device port that corresponds to a given host port.""" |
| 154 with _FileLock(Forwarder._LOCK_PATH): | 156 with _FileLock(Forwarder._LOCK_PATH): |
| 155 (_device_serial, device_port) = Forwarder._GetInstanceLocked( | 157 (device_serial, device_port) = Forwarder._GetInstanceLocked( |
| 156 None)._host_to_device_port_map.get(host_port) | 158 None)._host_to_device_port_map.get(host_port) |
| 157 return device_port | 159 return device_port |
| 158 | 160 |
| 159 @staticmethod | 161 @staticmethod |
| 160 def RemoveHostLog(): | 162 def RemoveHostLog(): |
| 161 if os.path.exists(Forwarder._HOST_FORWARDER_LOG): | 163 if os.path.exists(Forwarder._HOST_FORWARDER_LOG): |
| 162 os.unlink(Forwarder._HOST_FORWARDER_LOG) | 164 os.unlink(Forwarder._HOST_FORWARDER_LOG) |
| 163 | 165 |
| 164 @staticmethod | 166 @staticmethod |
| 165 def GetHostLog(): | 167 def GetHostLog(): |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 Note that the global lock must be acquired before calling this method. | 312 Note that the global lock must be acquired before calling this method. |
| 311 | 313 |
| 312 Args: | 314 Args: |
| 313 adb: Instance of AndroidCommands for talking to the device. | 315 adb: Instance of AndroidCommands for talking to the device. |
| 314 tool: Wrapper tool (e.g. valgrind) that can be used to execute the device | 316 tool: Wrapper tool (e.g. valgrind) that can be used to execute the device |
| 315 forwarder (see valgrind_tools.py). | 317 forwarder (see valgrind_tools.py). |
| 316 """ | 318 """ |
| 317 logging.info('Killing device_forwarder.') | 319 logging.info('Killing device_forwarder.') |
| 318 if not adb.FileExistsOnDevice(Forwarder._DEVICE_FORWARDER_PATH): | 320 if not adb.FileExistsOnDevice(Forwarder._DEVICE_FORWARDER_PATH): |
| 319 return | 321 return |
| 320 adb.GetShellCommandStatusAndOutput( | 322 (exit_code, output) = adb.GetShellCommandStatusAndOutput( |
| 321 '%s %s --kill-server' % (tool.GetUtilWrapper(), | 323 '%s %s --kill-server' % (tool.GetUtilWrapper(), |
| 322 Forwarder._DEVICE_FORWARDER_PATH)) | 324 Forwarder._DEVICE_FORWARDER_PATH)) |
| 323 # TODO(pliard): Remove the following call to KillAllBlocking() when we are | 325 # TODO(pliard): Remove the following call to KillAllBlocking() when we are |
| 324 # sure that the old version of device_forwarder (not supporting | 326 # sure that the old version of device_forwarder (not supporting |
| 325 # 'kill-server') is not running on the bots anymore. | 327 # 'kill-server') is not running on the bots anymore. |
| 326 timeout_sec = 5 | 328 timeout_sec = 5 |
| 327 processes_killed = adb.KillAllBlocking('device_forwarder', timeout_sec) | 329 processes_killed = adb.KillAllBlocking('device_forwarder', timeout_sec) |
| 328 if not processes_killed: | 330 if not processes_killed: |
| 329 pids = adb.ExtractPid('device_forwarder') | 331 pids = adb.ExtractPid('device_forwarder') |
| 330 if pids: | 332 if pids: |
| 331 raise Exception('Timed out while killing device_forwarder') | 333 raise Exception('Timed out while killing device_forwarder') |
| OLD | NEW |