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.

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

mercurial