def timeboxed_func(*args, **kwargs): # There is no perfect way to timeout an arbitrary function in # Python. See, for example, Eli Bendersky's blog post: # http://eli.thegreenplace.net/2011/08/22/how-not-to-set-a-timeout-on-a-computation-in-python/ #TODO use CPython's thread killing instead. see https://bitbucket.org/denis/gevent/src/a21725584355/greentest/test_threading.py # # In this case, we have the additional constraint of needing to # propagate the current environment, in case that is required by # the test function. # # We have chosen to run the target function in parallel, and to # allow it to finish on its own if it runs too long. We will use # threads for parallel processing (rather than, say, the # multiprocessing module) because that makes it easier to replicate # the target function's execution environment. #TODO not sure if this difference is as big as i think #TODO Provide a way to copy thread local storage (and any other thread context we can think of) across to the new thread # Callbacks to do this manually... target = _TimeoutFunctionThread(lambda : func(*args, **kwargs)) target.start() # Wait for the target function to finish executing, or else reach # it's time limit if not target.finished.wait(max_time): raise TimeExpired("%s could not be run within %s seconds" % (func.__name__, max_time)) assert target.finished.is_set() # Return result for original function return target.get_result()
def newfunc(*arg, **kwargs): timer = Timer(limit, handler) try: log.debug('starting timer in %s for %s', str(datetime.datetime.now()), str(limit)) timer.start() ret = func(*arg, **kwargs) except KeyboardInterrupt: if timer.isAlive: timer.cancel() raise except: if timer.isAlive(): timer.cancel() log.debug('canceled timer in %s because of failure', str(datetime.datetime.now())) raise else: raise TimeExpired, 'Time expired ( and test raised: ' \ + str(sys.exc_info()) + ')', sys.exc_info()[2] if timer.isAlive(): timer.cancel() log.debug('canceled timer in %s', str(datetime.datetime.now())) else: log.debug('timer has expired', str(datetime.datetime.now())) raise TimeExpired("time limit exceeded") return ret
def wrapper(*args, **kargs): q = Queue() def callback(value): q.put(None) def errback(failure): # Retrieve and save full exception info try: failure.raiseException() except: q.put(sys.exc_info()) def g(): try: d = func(*args, **kargs) try: d.addCallbacks(callback, errback) # Check for a common mistake and display a nice error # message except AttributeError: raise TypeError("you must return a twisted Deferred " "from your test case!") # Catch exceptions raised in the test body (from the # Twisted thread) except: q.put(sys.exc_info()) reactor.callFromThread(g) try: error = q.get(timeout=timeout) except Empty: raise TimeExpired("timeout expired before end of test (%f s.)" % timeout) # Re-raise all exceptions if error is not None: exc_type, exc_value, tb = error raise exc_type(exc_value).with_traceback(tb)
def newfunc(*args, **kwargs): signal.signal(signal.SIGALRM, _timeout_signal_handler) try: signal.alarm(int(limit + 1.0 // 1)) rc = func(*args, **kwargs) signal.alarm(0) except TimeExpired: exc_cls, exc, tb = sys.exc_info() raise exc_cls, TimeExpired("Time limit (%s) exceeded" % limit), tb finally: signal.signal(signal.SIGALRM, signal.SIG_IGN) return rc
def timeout_handler(signum, frame): raise TimeExpired('Timeout expired before end of test %s' % self._testID)