OLD | NEW |
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. |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 tombstones: a list of tombstones. | 158 tombstones: a list of tombstones. |
159 """ | 159 """ |
160 if not tombstones: | 160 if not tombstones: |
161 logging.warning('No tombstones to resolve.') | 161 logging.warning('No tombstones to resolve.') |
162 return | 162 return |
163 if len(tombstones) == 1: | 163 if len(tombstones) == 1: |
164 data = [_ResolveTombstone(tombstones[0])] | 164 data = [_ResolveTombstone(tombstones[0])] |
165 else: | 165 else: |
166 pool = multiprocessing.Pool(processes=jobs) | 166 pool = multiprocessing.Pool(processes=jobs) |
167 data = pool.map(_ResolveTombstone, tombstones) | 167 data = pool.map(_ResolveTombstone, tombstones) |
168 resolved_tombstones = [] | |
169 for tombstone in data: | 168 for tombstone in data: |
170 resolved_tombstones.extend(tombstone) | 169 for line in tombstone: |
171 return resolved_tombstones | 170 logging.info(line) |
172 | 171 |
173 def _GetTombstonesForDevice(device, resolve_all_tombstones, | 172 |
174 include_stack_symbols, | 173 def _GetTombstonesForDevice(device, args): |
175 wipe_tombstones): | |
176 """Returns a list of tombstones on a given device. | 174 """Returns a list of tombstones on a given device. |
177 | 175 |
178 Args: | 176 Args: |
179 device: An instance of DeviceUtils. | 177 device: An instance of DeviceUtils. |
180 resolve_all_tombstone: Whether to resolve every tombstone. | 178 args: command line arguments |
181 include_stack_symbols: Whether to include symbols for stack data. | |
182 wipe_tombstones: Whether to wipe tombstones. | |
183 """ | 179 """ |
184 ret = [] | 180 ret = [] |
185 all_tombstones = list(_ListTombstones(device)) | 181 all_tombstones = list(_ListTombstones(device)) |
186 if not all_tombstones: | 182 if not all_tombstones: |
187 logging.warning('No tombstones.') | 183 logging.warning('No tombstones.') |
188 return ret | 184 return ret |
189 | 185 |
190 # Sort the tombstones in date order, descending | 186 # Sort the tombstones in date order, descending |
191 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1])) | 187 all_tombstones.sort(cmp=lambda a, b: cmp(b[1], a[1])) |
192 | 188 |
193 # Only resolve the most recent unless --all-tombstones given. | 189 # Only resolve the most recent unless --all-tombstones given. |
194 tombstones = all_tombstones if resolve_all_tombstones else [all_tombstones[0]] | 190 tombstones = all_tombstones if args.all_tombstones else [all_tombstones[0]] |
195 | 191 |
196 device_now = _GetDeviceDateTime(device) | 192 device_now = _GetDeviceDateTime(device) |
197 try: | 193 try: |
198 for tombstone_file, tombstone_time in tombstones: | 194 for tombstone_file, tombstone_time in tombstones: |
199 ret += [{'serial': str(device), | 195 ret += [{'serial': str(device), |
200 'device_abi': device.product_cpu_abi, | 196 'device_abi': device.product_cpu_abi, |
201 'device_now': device_now, | 197 'device_now': device_now, |
202 'time': tombstone_time, | 198 'time': tombstone_time, |
203 'file': tombstone_file, | 199 'file': tombstone_file, |
204 'stack': include_stack_symbols, | 200 'stack': args.stack, |
205 'data': _GetTombstoneData(device, tombstone_file)}] | 201 'data': _GetTombstoneData(device, tombstone_file)}] |
206 except device_errors.CommandFailedError: | 202 except device_errors.CommandFailedError: |
207 for entry in device.StatDirectory( | 203 for entry in device.StatDirectory( |
208 '/data/tombstones', as_root=True, timeout=60): | 204 '/data/tombstones', as_root=True, timeout=60): |
209 logging.info('%s: %s', str(device), entry) | 205 logging.info('%s: %s', str(device), entry) |
210 raise | 206 raise |
211 | 207 |
212 # Erase all the tombstones if desired. | 208 # Erase all the tombstones if desired. |
213 if wipe_tombstones: | 209 if args.wipe_tombstones: |
214 for tombstone_file, _ in all_tombstones: | 210 for tombstone_file, _ in all_tombstones: |
215 _EraseTombstone(device, tombstone_file) | 211 _EraseTombstone(device, tombstone_file) |
216 | 212 |
217 return ret | 213 return ret |
218 | 214 |
219 def ClearAllTombstones(device): | |
220 """Clear all tombstones in the device. | |
221 | |
222 Args: | |
223 device: An instance of DeviceUtils. | |
224 """ | |
225 all_tombstones = list(_ListTombstones(device)) | |
226 if not all_tombstones: | |
227 logging.warning('No tombstones to clear.') | |
228 | |
229 for tombstone_file, _ in all_tombstones: | |
230 _EraseTombstone(device, tombstone_file) | |
231 | |
232 def ResolveTombstones(device, resolve_all_tombstones, include_stack_symbols, | |
233 wipe_tombstones, jobs=4): | |
234 """Resolve tombstones in the device. | |
235 | |
236 Args: | |
237 device: An instance of DeviceUtils. | |
238 resolve_all_tombstone: Whether to resolve every tombstone. | |
239 include_stack_symbols: Whether to include symbols for stack data. | |
240 wipe_tombstones: Whether to wipe tombstones. | |
241 jobs: Number of jobs to use when processing multiple crash stacks. | |
242 """ | |
243 return _ResolveTombstones(jobs, | |
244 _GetTombstonesForDevice(device, | |
245 resolve_all_tombstones, | |
246 include_stack_symbols, | |
247 wipe_tombstones)) | |
248 | 215 |
249 def main(): | 216 def main(): |
250 custom_handler = logging.StreamHandler(sys.stdout) | 217 custom_handler = logging.StreamHandler(sys.stdout) |
251 custom_handler.setFormatter(run_tests_helper.CustomFormatter()) | 218 custom_handler.setFormatter(run_tests_helper.CustomFormatter()) |
252 logging.getLogger().addHandler(custom_handler) | 219 logging.getLogger().addHandler(custom_handler) |
253 logging.getLogger().setLevel(logging.INFO) | 220 logging.getLogger().setLevel(logging.INFO) |
254 | 221 |
255 parser = argparse.ArgumentParser() | 222 parser = argparse.ArgumentParser() |
256 parser.add_argument('--device', | 223 parser.add_argument('--device', |
257 help='The serial number of the device. If not specified ' | 224 help='The serial number of the device. If not specified ' |
(...skipping 28 matching lines...) Expand all Loading... |
286 constants.CheckOutputDirectory() | 253 constants.CheckOutputDirectory() |
287 | 254 |
288 if args.device: | 255 if args.device: |
289 devices = [device_utils.DeviceUtils(args.device)] | 256 devices = [device_utils.DeviceUtils(args.device)] |
290 else: | 257 else: |
291 devices = device_utils.DeviceUtils.HealthyDevices(blacklist) | 258 devices = device_utils.DeviceUtils.HealthyDevices(blacklist) |
292 | 259 |
293 # This must be done serially because strptime can hit a race condition if | 260 # This must be done serially because strptime can hit a race condition if |
294 # used for the first time in a multithreaded environment. | 261 # used for the first time in a multithreaded environment. |
295 # http://bugs.python.org/issue7980 | 262 # http://bugs.python.org/issue7980 |
| 263 tombstones = [] |
296 for device in devices: | 264 for device in devices: |
297 resolved_tombstones = ResolveTombstones( | 265 tombstones += _GetTombstonesForDevice(device, args) |
298 device, args.all_tombstones, | 266 |
299 args.stack, args.wipe_tombstones, args.jobs) | 267 _ResolveTombstones(args.jobs, tombstones) |
300 for line in resolved_tombstones: | 268 |
301 logging.info(line) | |
302 | 269 |
303 if __name__ == '__main__': | 270 if __name__ == '__main__': |
304 sys.exit(main()) | 271 sys.exit(main()) |
OLD | NEW |