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

Side by Side Diff: build/android/tombstones.py

Issue 1002293004: [Android] Make failure to find tombstones nonfatal. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2013 The Chromium Authors. All rights reserved. 3 # Copyright 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 # 6 #
7 # Find the most recent tombstone file(s) on all connected devices 7 # Find the most recent tombstone file(s) on all connected devices
8 # and prints their stacks. 8 # and prints their stacks.
9 # 9 #
10 # Assumes tombstone file was created with current symbols. 10 # Assumes tombstone file was created with current symbols.
11 11
12 import datetime 12 import datetime
13 import itertools
14 import logging
13 import multiprocessing 15 import multiprocessing
14 import os 16 import os
15 import re 17 import re
16 import subprocess 18 import subprocess
17 import sys 19 import sys
18 import optparse 20 import optparse
19 21
20 from pylib import android_commands 22 from pylib import android_commands
21 from pylib.device import device_errors 23 from pylib.device import device_errors
22 from pylib.device import device_utils 24 from pylib.device import device_utils
25 from pylib.utils import run_tests_helper
23 26
24 27
25 _TZ_UTC = {'TZ': 'UTC'} 28 _TZ_UTC = {'TZ': 'UTC'}
26 29
27 def _ListTombstones(device): 30 def _ListTombstones(device):
28 """List the tombstone files on the device. 31 """List the tombstone files on the device.
29 32
30 Args: 33 Args:
31 device: An instance of DeviceUtils. 34 device: An instance of DeviceUtils.
32 35
33 Yields: 36 Yields:
34 Tuples of (tombstone filename, date time of file on device). 37 Tuples of (tombstone filename, date time of file on device).
35 """ 38 """
36 lines = device.RunShellCommand( 39 try:
37 ['ls', '-a', '-l', '/data/tombstones'], 40 lines = device.RunShellCommand(
38 as_root=True, check_return=True, env=_TZ_UTC, timeout=60) 41 ['ls', '-a', '-l', '/data/tombstones'],
39 for line in lines: 42 as_root=True, check_return=True, env=_TZ_UTC, timeout=60)
40 if 'tombstone' in line and not 'No such file or directory' in line: 43 for line in lines:
41 details = line.split() 44 if 'tombstone' in line and not 'No such file or directory' in line:
42 t = datetime.datetime.strptime(details[-3] + ' ' + details[-2], 45 details = line.split()
43 '%Y-%m-%d %H:%M') 46 t = datetime.datetime.strptime(details[-3] + ' ' + details[-2],
44 yield details[-1], t 47 '%Y-%m-%d %H:%M')
48 yield details[-1], t
49 except device_errors.CommandFailedError:
50 logging.exception('Could not retrieve tombstones.')
51 raise StopIteration
jbudorick 2015/03/18 21:04:51 This gets raised anyway, so I removed the explicit
45 52
46 53
47 def _GetDeviceDateTime(device): 54 def _GetDeviceDateTime(device):
48 """Determine the date time on the device. 55 """Determine the date time on the device.
49 56
50 Args: 57 Args:
51 device: An instance of DeviceUtils. 58 device: An instance of DeviceUtils.
52 59
53 Returns: 60 Returns:
54 A datetime instance. 61 A datetime instance.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 break 133 break
127 yield line 134 yield line
128 135
129 136
130 def _ResolveTombstone(tombstone): 137 def _ResolveTombstone(tombstone):
131 lines = [] 138 lines = []
132 lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) + 139 lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) +
133 ', about this long ago: ' + 140 ', about this long ago: ' +
134 (str(tombstone['device_now'] - tombstone['time']) + 141 (str(tombstone['device_now'] - tombstone['time']) +
135 ' Device: ' + tombstone['serial'])] 142 ' Device: ' + tombstone['serial'])]
136 print '\n'.join(lines) 143 logging.info('\n'.join(lines))
137 print 'Resolving...' 144 logging.info('Resolving...')
138 lines += _ResolveSymbols(tombstone['data'], tombstone['stack'], 145 lines += _ResolveSymbols(tombstone['data'], tombstone['stack'],
139 tombstone['device_abi']) 146 tombstone['device_abi'])
140 return lines 147 return lines
141 148
142 149
143 def _ResolveTombstones(jobs, tombstones): 150 def _ResolveTombstones(jobs, tombstones):
144 """Resolve a list of tombstones. 151 """Resolve a list of tombstones.
145 152
146 Args: 153 Args:
147 jobs: the number of jobs to use with multiprocess. 154 jobs: the number of jobs to use with multiprocess.
148 tombstones: a list of tombstones. 155 tombstones: a list of tombstones.
149 """ 156 """
150 if not tombstones: 157 if not tombstones:
151 print 'No device attached? Or no tombstones?' 158 logging.warning('No tombstones to resolve.')
152 return 159 return
153 if len(tombstones) == 1: 160 if len(tombstones) == 1:
154 data = _ResolveTombstone(tombstones[0]) 161 data = _ResolveTombstone(tombstones[0])
155 else: 162 else:
156 pool = multiprocessing.Pool(processes=jobs) 163 pool = multiprocessing.Pool(processes=jobs)
157 data = pool.map(_ResolveTombstone, tombstones) 164 data = pool.map(_ResolveTombstone, tombstones)
158 data = ['\n'.join(d) for d in data] 165 # data = ['\n'.join(d) for d in data]
159 print '\n'.join(data) 166 for d in data:
167 logging.info(d)
168 # logging.info('\n'.join(data))
160 169
161 170
162 def _GetTombstonesForDevice(device, options): 171 def _GetTombstonesForDevice(device, options):
163 """Returns a list of tombstones on a given device. 172 """Returns a list of tombstones on a given device.
164 173
165 Args: 174 Args:
166 device: An instance of DeviceUtils. 175 device: An instance of DeviceUtils.
167 options: command line arguments from OptParse 176 options: command line arguments from OptParse
168 """ 177 """
169 ret = [] 178 ret = []
170 all_tombstones = list(_ListTombstones(device)) 179 all_tombstones = list(_ListTombstones(device))
171 if not all_tombstones: 180 if not all_tombstones:
172 print 'No device attached? Or no tombstones?' 181 logging.warning('No tombstones.')
173 return ret 182 return ret
174 183
175 # Sort the tombstones in date order, descending 184 # Sort the tombstones in date order, descending
176 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1])) 185 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1]))
177 186
178 # Only resolve the most recent unless --all-tombstones given. 187 # Only resolve the most recent unless --all-tombstones given.
179 tombstones = all_tombstones if options.all_tombstones else [all_tombstones[0]] 188 tombstones = all_tombstones if options.all_tombstones else [all_tombstones[0]]
180 189
181 device_now = _GetDeviceDateTime(device) 190 device_now = _GetDeviceDateTime(device)
182 try: 191 try:
183 for tombstone_file, tombstone_time in tombstones: 192 for tombstone_file, tombstone_time in tombstones:
184 ret += [{'serial': str(device), 193 ret += [{'serial': str(device),
185 'device_abi': device.product_cpu_abi, 194 'device_abi': device.product_cpu_abi,
186 'device_now': device_now, 195 'device_now': device_now,
187 'time': tombstone_time, 196 'time': tombstone_time,
188 'file': tombstone_file, 197 'file': tombstone_file,
189 'stack': options.stack, 198 'stack': options.stack,
190 'data': _GetTombstoneData(device, tombstone_file)}] 199 'data': _GetTombstoneData(device, tombstone_file)}]
191 except device_errors.CommandFailedError: 200 except device_errors.CommandFailedError:
192 for line in device.RunShellCommand( 201 for line in device.RunShellCommand(
193 ['ls', '-a', '-l', '/data/tombstones'], 202 ['ls', '-a', '-l', '/data/tombstones'],
194 as_root=True, check_return=True, env=_TZ_UTC, timeout=60): 203 as_root=True, check_return=True, env=_TZ_UTC, timeout=60):
195 print '%s: %s' % (str(device), line) 204 logging.info('%s: %s', str(device), line)
196 raise 205 raise
197 206
198 # Erase all the tombstones if desired. 207 # Erase all the tombstones if desired.
199 if options.wipe_tombstones: 208 if options.wipe_tombstones:
200 for tombstone_file, _ in all_tombstones: 209 for tombstone_file, _ in all_tombstones:
201 _EraseTombstone(device, tombstone_file) 210 _EraseTombstone(device, tombstone_file)
202 211
203 return ret 212 return ret
204 213
205 214
206 def main(): 215 def main():
216 custom_handler = logging.StreamHandler(sys.stdout)
217 custom_handler.setFormatter(run_tests_helper.CustomFormatter())
218 logging.getLogger().addHandler(custom_handler)
219 logging.getLogger().setLevel(logging.INFO)
220
207 parser = optparse.OptionParser() 221 parser = optparse.OptionParser()
208 parser.add_option('--device', 222 parser.add_option('--device',
209 help='The serial number of the device. If not specified ' 223 help='The serial number of the device. If not specified '
210 'will use all devices.') 224 'will use all devices.')
211 parser.add_option('-a', '--all-tombstones', action='store_true', 225 parser.add_option('-a', '--all-tombstones', action='store_true',
212 help="""Resolve symbols for all tombstones, rather than just 226 help="""Resolve symbols for all tombstones, rather than just
213 the most recent""") 227 the most recent""")
214 parser.add_option('-s', '--stack', action='store_true', 228 parser.add_option('-s', '--stack', action='store_true',
215 help='Also include symbols for stack data') 229 help='Also include symbols for stack data')
216 parser.add_option('-w', '--wipe-tombstones', action='store_true', 230 parser.add_option('-w', '--wipe-tombstones', action='store_true',
217 help='Erase all tombstones from device after processing') 231 help='Erase all tombstones from device after processing')
218 parser.add_option('-j', '--jobs', type='int', 232 parser.add_option('-j', '--jobs', type='int',
219 default=4, 233 default=4,
220 help='Number of jobs to use when processing multiple ' 234 help='Number of jobs to use when processing multiple '
221 'crash stacks.') 235 'crash stacks.')
222 options, _ = parser.parse_args() 236 options, _ = parser.parse_args()
223 237
224 if options.device: 238 if options.device:
225 devices = [options.device] 239 devices = [options.device]
226 else: 240 else:
227 devices = android_commands.GetAttachedDevices() 241 devices = android_commands.GetAttachedDevices()
228 242
229 tombstones = [] 243 parallel_devices = device_utils.DeviceUtils.parallel(devices)
230 for device_serial in devices: 244 tombstones = list(itertools.chain(
231 device = device_utils.DeviceUtils(device_serial) 245 *parallel_devices.pMap(_GetTombstonesForDevice, options).pGet(None)))
232 tombstones += _GetTombstonesForDevice(device, options)
233 246
234 _ResolveTombstones(options.jobs, tombstones) 247 _ResolveTombstones(options.jobs, tombstones)
235 248
236 if __name__ == '__main__': 249 if __name__ == '__main__':
237 sys.exit(main()) 250 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698