Change implementation of timing out to not leave lingering threads

This commit is contained in:
Tim Savannah 2016-03-18 13:59:20 -04:00
parent edfc9b8d4a
commit a8e096d528
3 changed files with 8 additions and 67 deletions

View File

@ -1,3 +1,6 @@
* 2.0.0 - Mar 18 2016
- Change implementation to not leave lingering threads after a timeout occurs
* 1.0.1 - Mar 15 2016
- Remove debugging print
- Note that it has been explicitly tested on 2.7, 3.4, and 3.5 in README.

View File

@ -5,73 +5,11 @@
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import threading
import time
__version__ = '1.0.1'
__version_tuple__ = (1, 0, 1)
__version__ = '2.0.0'
__version_tuple__ = (2, 0, 0)
__all__ = ('func_timeout', 'FunctionTimedOut')
def func_timeout(timeout, func, args=(), kwargs=None):
'''
func_timeout - Runs the given function for up to #timeout# seconds.
Raises any exceptions #func# would raise, returns what #func# would return (unless timeout is exceeded), in which case it raises FunctionTimedOut
@param timeout <float> - Maximum number of seconds to run #func# before terminating
@param func <function> - The function to call
@param args <tuple> - Any ordered arguments to pass to the function
@param kwargs <dict/None> - Keyword arguments to pass to the function.
@raises - FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised
@return - The return value that #func# gives
'''
if not kwargs:
kwargs = {}
if not args:
args = ()
ret = []
exception = []
def funcwrap(args2, kwargs2):
try:
ret.append( func(*args2, **kwargs2) )
except Exception as e:
exception.append(e)
thread = threading.Thread(target=funcwrap, args=(args, kwargs))
thread.start()
thread.join(timeout)
if thread.isAlive():
doRaiseCantStop = False
thread.isDaemon = True
try:
if hasattr(thread, '_tstate_lock'):
# 3.5
thread._tstate_lock.release()
elif hasattr(thread, '_Thread__stop'):
# 2.7
thread._Thread__stop()
else:
doRaiseCantStop = True
except:
pass
if doRaiseCantStop is True:
raise NotImplementedError('function timeouts not supported on this system.\n')
if exception:
raise exception[0]
if ret:
return ret[0]
raise FunctionTimedOut('Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(func.__name__, str(args), str(kwargs), timeout))
class FunctionTimedOut(Exception):
pass
from .exceptions import FunctionTimedOut
from .dafunc import func_timeout

View File

@ -30,7 +30,7 @@ if __name__ == '__main__':
log_description = summary
setup(name='func_timeout',
version='1.0.1',
version='2.0.0',
packages=['func_timeout'],
author='Tim Savannah',
author_email='kata198@gmail.com',