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

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

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