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

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

Issue 2101243005: Add a snapshot of flutter/engine/src/build to our sdk (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: add README.dart Created 4 years, 5 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 | « build/android/tests/symbolize/libb.so ('k') | build/android/update_verification.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
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
5 # found in the LICENSE file.
6 #
7 # Find the most recent tombstone file(s) on all connected devices
8 # and prints their stacks.
9 #
10 # Assumes tombstone file was created with current symbols.
11
12 import datetime
13 import itertools
14 import logging
15 import multiprocessing
16 import os
17 import re
18 import subprocess
19 import sys
20 import optparse
21
22 from pylib.device import adb_wrapper
23 from pylib.device import device_errors
24 from pylib.device import device_utils
25 from pylib.utils import run_tests_helper
26
27
28 _TZ_UTC = {'TZ': 'UTC'}
29
30 def _ListTombstones(device):
31 """List the tombstone files on the device.
32
33 Args:
34 device: An instance of DeviceUtils.
35
36 Yields:
37 Tuples of (tombstone filename, date time of file on device).
38 """
39 try:
40 lines = device.RunShellCommand(
41 ['ls', '-a', '-l', '/data/tombstones'],
42 as_root=True, check_return=True, env=_TZ_UTC, timeout=60)
43 for line in lines:
44 if 'tombstone' in line and not 'No such file or directory' in line:
45 details = line.split()
46 t = datetime.datetime.strptime(details[-3] + ' ' + details[-2],
47 '%Y-%m-%d %H:%M')
48 yield details[-1], t
49 except device_errors.CommandFailedError:
50 logging.exception('Could not retrieve tombstones.')
51
52
53 def _GetDeviceDateTime(device):
54 """Determine the date time on the device.
55
56 Args:
57 device: An instance of DeviceUtils.
58
59 Returns:
60 A datetime instance.
61 """
62 device_now_string = device.RunShellCommand(
63 ['date'], check_return=True, env=_TZ_UTC)
64 return datetime.datetime.strptime(
65 device_now_string[0], '%a %b %d %H:%M:%S %Z %Y')
66
67
68 def _GetTombstoneData(device, tombstone_file):
69 """Retrieve the tombstone data from the device
70
71 Args:
72 device: An instance of DeviceUtils.
73 tombstone_file: the tombstone to retrieve
74
75 Returns:
76 A list of lines
77 """
78 return device.ReadFile(
79 '/data/tombstones/' + tombstone_file, as_root=True).splitlines()
80
81
82 def _EraseTombstone(device, tombstone_file):
83 """Deletes a tombstone from the device.
84
85 Args:
86 device: An instance of DeviceUtils.
87 tombstone_file: the tombstone to delete.
88 """
89 return device.RunShellCommand(
90 ['rm', '/data/tombstones/' + tombstone_file],
91 as_root=True, check_return=True)
92
93
94 def _DeviceAbiToArch(device_abi):
95 # The order of this list is significant to find the more specific match (e.g.,
96 # arm64) before the less specific (e.g., arm).
97 arches = ['arm64', 'arm', 'x86_64', 'x86_64', 'x86', 'mips']
98 for arch in arches:
99 if arch in device_abi:
100 return arch
101 raise RuntimeError('Unknown device ABI: %s' % device_abi)
102
103 def _ResolveSymbols(tombstone_data, include_stack, device_abi):
104 """Run the stack tool for given tombstone input.
105
106 Args:
107 tombstone_data: a list of strings of tombstone data.
108 include_stack: boolean whether to include stack data in output.
109 device_abi: the default ABI of the device which generated the tombstone.
110
111 Yields:
112 A string for each line of resolved stack output.
113 """
114 # Check if the tombstone data has an ABI listed, if so use this in preference
115 # to the device's default ABI.
116 for line in tombstone_data:
117 found_abi = re.search('ABI: \'(.+?)\'', line)
118 if found_abi:
119 device_abi = found_abi.group(1)
120 arch = _DeviceAbiToArch(device_abi)
121 if not arch:
122 return
123
124 stack_tool = os.path.join(os.path.dirname(__file__), '..', '..',
125 'third_party', 'android_platform', 'development',
126 'scripts', 'stack')
127 proc = subprocess.Popen([stack_tool, '--arch', arch], stdin=subprocess.PIPE,
128 stdout=subprocess.PIPE)
129 output = proc.communicate(input='\n'.join(tombstone_data))[0]
130 for line in output.split('\n'):
131 if not include_stack and 'Stack Data:' in line:
132 break
133 yield line
134
135
136 def _ResolveTombstone(tombstone):
137 lines = []
138 lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) +
139 ', about this long ago: ' +
140 (str(tombstone['device_now'] - tombstone['time']) +
141 ' Device: ' + tombstone['serial'])]
142 logging.info('\n'.join(lines))
143 logging.info('Resolving...')
144 lines += _ResolveSymbols(tombstone['data'], tombstone['stack'],
145 tombstone['device_abi'])
146 return lines
147
148
149 def _ResolveTombstones(jobs, tombstones):
150 """Resolve a list of tombstones.
151
152 Args:
153 jobs: the number of jobs to use with multiprocess.
154 tombstones: a list of tombstones.
155 """
156 if not tombstones:
157 logging.warning('No tombstones to resolve.')
158 return
159 if len(tombstones) == 1:
160 data = [_ResolveTombstone(tombstones[0])]
161 else:
162 pool = multiprocessing.Pool(processes=jobs)
163 data = pool.map(_ResolveTombstone, tombstones)
164 for tombstone in data:
165 for line in tombstone:
166 logging.info(line)
167
168
169 def _GetTombstonesForDevice(device, options):
170 """Returns a list of tombstones on a given device.
171
172 Args:
173 device: An instance of DeviceUtils.
174 options: command line arguments from OptParse
175 """
176 ret = []
177 all_tombstones = list(_ListTombstones(device))
178 if not all_tombstones:
179 logging.warning('No tombstones.')
180 return ret
181
182 # Sort the tombstones in date order, descending
183 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1]))
184
185 # Only resolve the most recent unless --all-tombstones given.
186 tombstones = all_tombstones if options.all_tombstones else [all_tombstones[0]]
187
188 device_now = _GetDeviceDateTime(device)
189 try:
190 for tombstone_file, tombstone_time in tombstones:
191 ret += [{'serial': str(device),
192 'device_abi': device.product_cpu_abi,
193 'device_now': device_now,
194 'time': tombstone_time,
195 'file': tombstone_file,
196 'stack': options.stack,
197 'data': _GetTombstoneData(device, tombstone_file)}]
198 except device_errors.CommandFailedError:
199 for line in device.RunShellCommand(
200 ['ls', '-a', '-l', '/data/tombstones'],
201 as_root=True, check_return=True, env=_TZ_UTC, timeout=60):
202 logging.info('%s: %s', str(device), line)
203 raise
204
205 # Erase all the tombstones if desired.
206 if options.wipe_tombstones:
207 for tombstone_file, _ in all_tombstones:
208 _EraseTombstone(device, tombstone_file)
209
210 return ret
211
212
213 def main():
214 custom_handler = logging.StreamHandler(sys.stdout)
215 custom_handler.setFormatter(run_tests_helper.CustomFormatter())
216 logging.getLogger().addHandler(custom_handler)
217 logging.getLogger().setLevel(logging.INFO)
218
219 parser = optparse.OptionParser()
220 parser.add_option('--device',
221 help='The serial number of the device. If not specified '
222 'will use all devices.')
223 parser.add_option('-a', '--all-tombstones', action='store_true',
224 help="""Resolve symbols for all tombstones, rather than just
225 the most recent""")
226 parser.add_option('-s', '--stack', action='store_true',
227 help='Also include symbols for stack data')
228 parser.add_option('-w', '--wipe-tombstones', action='store_true',
229 help='Erase all tombstones from device after processing')
230 parser.add_option('-j', '--jobs', type='int',
231 default=4,
232 help='Number of jobs to use when processing multiple '
233 'crash stacks.')
234 options, _ = parser.parse_args()
235
236 if options.device:
237 devices = [device_utils.DeviceUtils(options.device)]
238 else:
239 devices = device_utils.DeviceUtils.HealthyDevices()
240
241 # This must be done serially because strptime can hit a race condition if
242 # used for the first time in a multithreaded environment.
243 # http://bugs.python.org/issue7980
244 tombstones = []
245 for device in devices:
246 tombstones += _GetTombstonesForDevice(device, options)
247
248 _ResolveTombstones(options.jobs, tombstones)
249
250
251 if __name__ == '__main__':
252 sys.exit(main())
OLDNEW
« no previous file with comments | « build/android/tests/symbolize/libb.so ('k') | build/android/update_verification.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698