media/webrtc/trunk/build/android/adb_logcat_monitor.py

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rwxr-xr-x

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 #!/usr/bin/env python
michael@0 2 #
michael@0 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 4 # Use of this source code is governed by a BSD-style license that can be
michael@0 5 # found in the LICENSE file.
michael@0 6
michael@0 7 """Saves logcats from all connected devices.
michael@0 8
michael@0 9 Usage: adb_logcat_monitor.py <base_dir> [<adb_binary_path>]
michael@0 10
michael@0 11 This script will repeatedly poll adb for new devices and save logcats
michael@0 12 inside the <base_dir> directory, which it attempts to create. The
michael@0 13 script will run until killed by an external signal. To test, run the
michael@0 14 script in a shell and <Ctrl>-C it after a while. It should be
michael@0 15 resilient across phone disconnects and reconnects and start the logcat
michael@0 16 early enough to not miss anything.
michael@0 17 """
michael@0 18
michael@0 19 import logging
michael@0 20 import os
michael@0 21 import re
michael@0 22 import shutil
michael@0 23 import signal
michael@0 24 import subprocess
michael@0 25 import sys
michael@0 26 import time
michael@0 27
michael@0 28 # Map from device_id -> (process, logcat_num)
michael@0 29 devices = {}
michael@0 30
michael@0 31
michael@0 32 class TimeoutException(Exception):
michael@0 33 """Exception used to signal a timeout."""
michael@0 34 pass
michael@0 35
michael@0 36
michael@0 37 class SigtermError(Exception):
michael@0 38 """Exception used to catch a sigterm."""
michael@0 39 pass
michael@0 40
michael@0 41
michael@0 42 def StartLogcatIfNecessary(device_id, adb_cmd, base_dir):
michael@0 43 """Spawns a adb logcat process if one is not currently running."""
michael@0 44 process, logcat_num = devices[device_id]
michael@0 45 if process:
michael@0 46 if process.poll() is None:
michael@0 47 # Logcat process is still happily running
michael@0 48 return
michael@0 49 else:
michael@0 50 logging.info('Logcat for device %s has died', device_id)
michael@0 51 error_filter = re.compile('- waiting for device -')
michael@0 52 for line in process.stderr:
michael@0 53 if not error_filter.match(line):
michael@0 54 logging.error(device_id + ': ' + line)
michael@0 55
michael@0 56 logging.info('Starting logcat %d for device %s', logcat_num,
michael@0 57 device_id)
michael@0 58 logcat_filename = 'logcat_%s_%03d' % (device_id, logcat_num)
michael@0 59 logcat_file = open(os.path.join(base_dir, logcat_filename), 'w')
michael@0 60 process = subprocess.Popen([adb_cmd, '-s', device_id,
michael@0 61 'logcat', '-v', 'threadtime'],
michael@0 62 stdout=logcat_file,
michael@0 63 stderr=subprocess.PIPE)
michael@0 64 devices[device_id] = (process, logcat_num + 1)
michael@0 65
michael@0 66
michael@0 67 def GetAttachedDevices(adb_cmd):
michael@0 68 """Gets the device list from adb.
michael@0 69
michael@0 70 We use an alarm in this function to avoid deadlocking from an external
michael@0 71 dependency.
michael@0 72
michael@0 73 Args:
michael@0 74 adb_cmd: binary to run adb
michael@0 75
michael@0 76 Returns:
michael@0 77 list of devices or an empty list on timeout
michael@0 78 """
michael@0 79 signal.alarm(2)
michael@0 80 try:
michael@0 81 out, err = subprocess.Popen([adb_cmd, 'devices'],
michael@0 82 stdout=subprocess.PIPE,
michael@0 83 stderr=subprocess.PIPE).communicate()
michael@0 84 if err:
michael@0 85 logging.warning('adb device error %s', err.strip())
michael@0 86 return re.findall('^(\w+)\tdevice$', out, re.MULTILINE)
michael@0 87 except TimeoutException:
michael@0 88 logging.warning('"adb devices" command timed out')
michael@0 89 return []
michael@0 90 except (IOError, OSError):
michael@0 91 logging.exception('Exception from "adb devices"')
michael@0 92 return []
michael@0 93 finally:
michael@0 94 signal.alarm(0)
michael@0 95
michael@0 96
michael@0 97 def main(base_dir, adb_cmd='adb'):
michael@0 98 """Monitor adb forever. Expects a SIGINT (Ctrl-C) to kill."""
michael@0 99 # We create the directory to ensure 'run once' semantics
michael@0 100 if os.path.exists(base_dir):
michael@0 101 print 'adb_logcat_monitor: %s already exists? Cleaning' % base_dir
michael@0 102 shutil.rmtree(base_dir, ignore_errors=True)
michael@0 103
michael@0 104 os.makedirs(base_dir)
michael@0 105 logging.basicConfig(filename=os.path.join(base_dir, 'eventlog'),
michael@0 106 level=logging.INFO,
michael@0 107 format='%(asctime)-2s %(levelname)-8s %(message)s')
michael@0 108
michael@0 109 # Set up the alarm for calling 'adb devices'. This is to ensure
michael@0 110 # our script doesn't get stuck waiting for a process response
michael@0 111 def TimeoutHandler(_, unused_frame):
michael@0 112 raise TimeoutException()
michael@0 113 signal.signal(signal.SIGALRM, TimeoutHandler)
michael@0 114
michael@0 115 # Handle SIGTERMs to ensure clean shutdown
michael@0 116 def SigtermHandler(_, unused_frame):
michael@0 117 raise SigtermError()
michael@0 118 signal.signal(signal.SIGTERM, SigtermHandler)
michael@0 119
michael@0 120 logging.info('Started with pid %d', os.getpid())
michael@0 121 pid_file_path = os.path.join(base_dir, 'LOGCAT_MONITOR_PID')
michael@0 122
michael@0 123 try:
michael@0 124 with open(pid_file_path, 'w') as f:
michael@0 125 f.write(str(os.getpid()))
michael@0 126 while True:
michael@0 127 for device_id in GetAttachedDevices(adb_cmd):
michael@0 128 if not device_id in devices:
michael@0 129 devices[device_id] = (None, 0)
michael@0 130
michael@0 131 for device in devices:
michael@0 132 # This will spawn logcat watchers for any device ever detected
michael@0 133 StartLogcatIfNecessary(device, adb_cmd, base_dir)
michael@0 134
michael@0 135 time.sleep(5)
michael@0 136 except SigtermError:
michael@0 137 logging.info('Received SIGTERM, shutting down')
michael@0 138 except:
michael@0 139 logging.exception('Unexpected exception in main.')
michael@0 140 finally:
michael@0 141 for process, _ in devices.itervalues():
michael@0 142 if process:
michael@0 143 try:
michael@0 144 process.terminate()
michael@0 145 except OSError:
michael@0 146 pass
michael@0 147 os.remove(pid_file_path)
michael@0 148
michael@0 149
michael@0 150 if __name__ == '__main__':
michael@0 151 if 2 <= len(sys.argv) <= 3:
michael@0 152 print 'adb_logcat_monitor: Initializing'
michael@0 153 sys.exit(main(*sys.argv[1:3]))
michael@0 154
michael@0 155 print 'Usage: %s <base_dir> [<adb_binary_path>]' % sys.argv[0]

mercurial