1# Copyright 2017 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6
7from devil import base_error
8from devil.android import device_errors
9
10logger = logging.getLogger(__name__)
11
12
13def RetryOnSystemCrash(f, device, retries=3):
14  """Retries the given function on a device crash.
15
16  If the provided function fails with a DeviceUnreachableError, this will wait
17  for the device to come back online, then retry the function.
18
19  Note that this uses the same retry scheme as timeout_retry.Run.
20
21  Args:
22    f: a unary callable that takes an instance of device_utils.DeviceUtils.
23    device: an instance of device_utils.DeviceUtils.
24    retries: the number of retries.
25  Returns:
26    Whatever f returns.
27  """
28  num_try = 1
29  while True:
30    try:
31      return f(device)
32    except device_errors.DeviceUnreachableError:
33      if num_try > retries:
34        logger.error('%d consecutive device crashes. No longer retrying.',
35                     num_try)
36        raise
37      try:
38        logger.warning('Device is unreachable. Waiting for recovery...')
39        # Treat the device being unreachable as an unexpected reboot and clear
40        # any cached state.
41        device.ClearCache()
42        device.WaitUntilFullyBooted()
43      except base_error.BaseError:
44        logger.exception('Device never recovered. X(')
45    num_try += 1
46