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