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

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

Issue 1015333002: [Android] Make failure to find tombstones nonfatal. (RELAND) (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.')
45 51
46 52
47 def _GetDeviceDateTime(device): 53 def _GetDeviceDateTime(device):
48 """Determine the date time on the device. 54 """Determine the date time on the device.
49 55
50 Args: 56 Args:
51 device: An instance of DeviceUtils. 57 device: An instance of DeviceUtils.
52 58
53 Returns: 59 Returns:
54 A datetime instance. 60 A datetime instance.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 break 132 break
127 yield line 133 yield line
128 134
129 135
130 def _ResolveTombstone(tombstone): 136 def _ResolveTombstone(tombstone):
131 lines = [] 137 lines = []
132 lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) + 138 lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) +
133 ', about this long ago: ' + 139 ', about this long ago: ' +
134 (str(tombstone['device_now'] - tombstone['time']) + 140 (str(tombstone['device_now'] - tombstone['time']) +
135 ' Device: ' + tombstone['serial'])] 141 ' Device: ' + tombstone['serial'])]
136 print '\n'.join(lines) 142 logging.info('\n'.join(lines))
137 print 'Resolving...' 143 logging.info('Resolving...')
138 lines += _ResolveSymbols(tombstone['data'], tombstone['stack'], 144 lines += _ResolveSymbols(tombstone['data'], tombstone['stack'],
139 tombstone['device_abi']) 145 tombstone['device_abi'])
140 return lines 146 return lines
141 147
142 148
143 def _ResolveTombstones(jobs, tombstones): 149 def _ResolveTombstones(jobs, tombstones):
144 """Resolve a list of tombstones. 150 """Resolve a list of tombstones.
145 151
146 Args: 152 Args:
147 jobs: the number of jobs to use with multiprocess. 153 jobs: the number of jobs to use with multiprocess.
148 tombstones: a list of tombstones. 154 tombstones: a list of tombstones.
149 """ 155 """
150 if not tombstones: 156 if not tombstones:
151 print 'No device attached? Or no tombstones?' 157 logging.warning('No tombstones to resolve.')
152 return 158 return
153 if len(tombstones) == 1: 159 if len(tombstones) == 1:
154 data = _ResolveTombstone(tombstones[0]) 160 data = _ResolveTombstone(tombstones[0])
155 else: 161 else:
156 pool = multiprocessing.Pool(processes=jobs) 162 pool = multiprocessing.Pool(processes=jobs)
157 data = pool.map(_ResolveTombstone, tombstones) 163 data = pool.map(_ResolveTombstone, tombstones)
158 data = ['\n'.join(d) for d in data] 164 for d in data:
159 print '\n'.join(data) 165 logging.info(d)
160 166
161 167
162 def _GetTombstonesForDevice(device, options): 168 def _GetTombstonesForDevice(device, options):
163 """Returns a list of tombstones on a given device. 169 """Returns a list of tombstones on a given device.
164 170
165 Args: 171 Args:
166 device: An instance of DeviceUtils. 172 device: An instance of DeviceUtils.
167 options: command line arguments from OptParse 173 options: command line arguments from OptParse
168 """ 174 """
169 ret = [] 175 ret = []
170 all_tombstones = list(_ListTombstones(device)) 176 all_tombstones = list(_ListTombstones(device))
171 if not all_tombstones: 177 if not all_tombstones:
172 print 'No device attached? Or no tombstones?' 178 logging.warning('No tombstones.')
173 return ret 179 return ret
174 180
175 # Sort the tombstones in date order, descending 181 # Sort the tombstones in date order, descending
176 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1])) 182 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1]))
177 183
178 # Only resolve the most recent unless --all-tombstones given. 184 # Only resolve the most recent unless --all-tombstones given.
179 tombstones = all_tombstones if options.all_tombstones else [all_tombstones[0]] 185 tombstones = all_tombstones if options.all_tombstones else [all_tombstones[0]]
180 186
181 device_now = _GetDeviceDateTime(device) 187 device_now = _GetDeviceDateTime(device)
182 try: 188 try:
183 for tombstone_file, tombstone_time in tombstones: 189 for tombstone_file, tombstone_time in tombstones:
184 ret += [{'serial': str(device), 190 ret += [{'serial': str(device),
185 'device_abi': device.product_cpu_abi, 191 'device_abi': device.product_cpu_abi,
186 'device_now': device_now, 192 'device_now': device_now,
187 'time': tombstone_time, 193 'time': tombstone_time,
188 'file': tombstone_file, 194 'file': tombstone_file,
189 'stack': options.stack, 195 'stack': options.stack,
190 'data': _GetTombstoneData(device, tombstone_file)}] 196 'data': _GetTombstoneData(device, tombstone_file)}]
191 except device_errors.CommandFailedError: 197 except device_errors.CommandFailedError:
192 for line in device.RunShellCommand( 198 for line in device.RunShellCommand(
193 ['ls', '-a', '-l', '/data/tombstones'], 199 ['ls', '-a', '-l', '/data/tombstones'],
194 as_root=True, check_return=True, env=_TZ_UTC, timeout=60): 200 as_root=True, check_return=True, env=_TZ_UTC, timeout=60):
195 print '%s: %s' % (str(device), line) 201 logging.info('%s: %s', str(device), line)
196 raise 202 raise
197 203
198 # Erase all the tombstones if desired. 204 # Erase all the tombstones if desired.
199 if options.wipe_tombstones: 205 if options.wipe_tombstones:
200 for tombstone_file, _ in all_tombstones: 206 for tombstone_file, _ in all_tombstones:
201 _EraseTombstone(device, tombstone_file) 207 _EraseTombstone(device, tombstone_file)
202 208
203 return ret 209 return ret
204 210
205 211
206 def main(): 212 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
207 parser = optparse.OptionParser() 218 parser = optparse.OptionParser()
208 parser.add_option('--device', 219 parser.add_option('--device',
209 help='The serial number of the device. If not specified ' 220 help='The serial number of the device. If not specified '
210 'will use all devices.') 221 'will use all devices.')
211 parser.add_option('-a', '--all-tombstones', action='store_true', 222 parser.add_option('-a', '--all-tombstones', action='store_true',
212 help="""Resolve symbols for all tombstones, rather than just 223 help="""Resolve symbols for all tombstones, rather than just
213 the most recent""") 224 the most recent""")
214 parser.add_option('-s', '--stack', action='store_true', 225 parser.add_option('-s', '--stack', action='store_true',
215 help='Also include symbols for stack data') 226 help='Also include symbols for stack data')
216 parser.add_option('-w', '--wipe-tombstones', action='store_true', 227 parser.add_option('-w', '--wipe-tombstones', action='store_true',
217 help='Erase all tombstones from device after processing') 228 help='Erase all tombstones from device after processing')
218 parser.add_option('-j', '--jobs', type='int', 229 parser.add_option('-j', '--jobs', type='int',
219 default=4, 230 default=4,
220 help='Number of jobs to use when processing multiple ' 231 help='Number of jobs to use when processing multiple '
221 'crash stacks.') 232 'crash stacks.')
222 options, _ = parser.parse_args() 233 options, _ = parser.parse_args()
223 234
224 if options.device: 235 if options.device:
225 devices = [options.device] 236 devices = [options.device]
226 else: 237 else:
227 devices = android_commands.GetAttachedDevices() 238 devices = android_commands.GetAttachedDevices()
228 239
240 # This must be done serially because strptime can hit a race condition if
jbudorick 2015/03/19 01:37:38 Forgot to upload the original patchset, but the fi
241 # used for the first time in a multithreaded environment.
242 # http://bugs.python.org/issue7980
229 tombstones = [] 243 tombstones = []
230 for device_serial in devices: 244 for device_serial in devices:
231 device = device_utils.DeviceUtils(device_serial) 245 device = device_utils.DeviceUtils(device_serial)
232 tombstones += _GetTombstonesForDevice(device, options) 246 tombstones += _GetTombstonesForDevice(device, options)
233 247
234 _ResolveTombstones(options.jobs, tombstones) 248 _ResolveTombstones(options.jobs, tombstones)
235 249
236 if __name__ == '__main__': 250 if __name__ == '__main__':
237 sys.exit(main()) 251 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