def Run(func, timeout, retries, args=[], kwargs={}):
  """Runs the passed function in a separate thread with timeouts and retries.

  Args:
    func: the function to be wrapped.
    timeout: the timeout in seconds for each try.
    retries: the number of retries.
    args: list of positional args to pass to |func|.
    kwargs: dictionary of keyword args to pass to |func|.

  Returns:
    The return value of func(*args, **kwargs).
  """
  # The return value uses a list because Python variables are references, not
  # values. Closures make a copy of the reference, so updating the closure's
  # reference wouldn't update where the original reference pointed.
  ret = [None]
  def RunOnTimeoutThread():
    ret[0] = func(*args, **kwargs)

  while True:
    try:
      name = 'TimeoutThread-for-%s' % threading.current_thread().name
      thread_group = reraiser_thread.ReraiserThreadGroup(
          [reraiser_thread.ReraiserThread(RunOnTimeoutThread, name=name)])
      thread_group.StartAll()
      thread_group.JoinAll(watchdog_timer.WatchdogTimer(timeout))
      return ret[0]
    except:
      if retries <= 0:
        raise
      retries -= 1
Exemple #2
0
    def testJoinTimeout(self):
        def f():
            pass

        event = threading.Event()

        def g():
            event.wait()

        group = reraiser_thread.ReraiserThreadGroup([
            reraiser_thread.ReraiserThread(g),
            reraiser_thread.ReraiserThread(f)
        ])
        group.StartAll()
        with self.assertRaises(reraiser_thread.TimeoutError):
            group.JoinAll(watchdog_timer.WatchdogTimer(0.01))
        event.set()
Exemple #3
0
    def testJoinRaise(self):
        def f():
            raise TestException

        group = reraiser_thread.ReraiserThreadGroup(
            [reraiser_thread.ReraiserThread(f) for _ in xrange(5)])
        group.StartAll()
        with self.assertRaises(TestException):
            group.JoinAll()
Exemple #4
0
    def testRaise(self):
        def f():
            raise TestException

        thread = reraiser_thread.ReraiserThread(f)
        thread.start()
        thread.join()
        with self.assertRaises(TestException):
            thread.ReraiseIfException()
Exemple #5
0
    def testInit(self):
        ran = [False] * 5

        def f(i):
            ran[i] = True

        group = reraiser_thread.ReraiserThreadGroup(
            [reraiser_thread.ReraiserThread(f, args=[i]) for i in range(5)])
        group.StartAll()
        group.JoinAll()
        for v in ran:
            self.assertTrue(v)
Exemple #6
0
    def testNominal(self):
        result = [None, None]

        def f(a, b=None):
            result[0] = a
            result[1] = b

        thread = reraiser_thread.ReraiserThread(f, [1], {'b': 2})
        thread.start()
        thread.join()
        self.assertEqual(result[0], 1)
        self.assertEqual(result[1], 2)