• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2013 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
5"""A utility to run functions with timeouts and retries."""
6
7import functools
8import threading
9
10import reraiser_thread
11import watchdog_timer
12
13
14def Run(func, timeout, retries, args=[], kwargs={}):
15  """Runs the passed function in a separate thread with timeouts and retries.
16
17  Args:
18    func: the function to be wrapped.
19    timeout: the timeout in seconds for each try.
20    retries: the number of retries.
21    args: list of positional args to pass to |func|.
22    kwargs: dictionary of keyword args to pass to |func|.
23
24  Returns:
25    The return value of func(*args, **kwargs).
26  """
27  # The return value uses a list because Python variables are references, not
28  # values. Closures make a copy of the reference, so updating the closure's
29  # reference wouldn't update where the original reference pointed.
30  ret = [None]
31  def RunOnTimeoutThread():
32    ret[0] = func(*args, **kwargs)
33
34  while True:
35    try:
36      name = 'TimeoutThread-for-%s' % threading.current_thread().name
37      thread_group = reraiser_thread.ReraiserThreadGroup(
38          [reraiser_thread.ReraiserThread(RunOnTimeoutThread, name=name)])
39      thread_group.StartAll()
40      thread_group.JoinAll(watchdog_timer.WatchdogTimer(timeout))
41      return ret[0]
42    except:
43      if retries <= 0:
44        raise
45      retries -= 1
46