66 lines
1.9 KiB
Python
66 lines
1.9 KiB
Python
|
|
from threading import Thread
|
||
|
|
import inspect
|
||
|
|
import ctypes
|
||
|
|
from functools import wraps
|
||
|
|
|
||
|
|
|
||
|
|
def _async_raise(tid, exctype):
|
||
|
|
"""raises the exception, performs cleanup if needed"""
|
||
|
|
tid = ctypes.c_long(tid)
|
||
|
|
if not inspect.isclass(exctype):
|
||
|
|
exctype = type(exctype)
|
||
|
|
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
|
||
|
|
if res == 0:
|
||
|
|
raise ValueError("invalid thread id")
|
||
|
|
elif res != 1:
|
||
|
|
# """if it returns a number greater than one, you're in trouble,
|
||
|
|
# and you should call it again with exc=NULL to revert the effect"""
|
||
|
|
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
|
||
|
|
raise SystemError("PyThreadState_SetAsyncExc failed")
|
||
|
|
|
||
|
|
|
||
|
|
def stop_thread(thread):
|
||
|
|
_async_raise(thread.ident, SystemExit)
|
||
|
|
|
||
|
|
|
||
|
|
class TimeoutException(Exception):
|
||
|
|
# print("timeout!")
|
||
|
|
pass
|
||
|
|
|
||
|
|
|
||
|
|
ThreadStop = stop_thread
|
||
|
|
|
||
|
|
|
||
|
|
def time_limited(timeout):
|
||
|
|
def decorator(function):
|
||
|
|
@wraps(function)
|
||
|
|
def wrapped_function(*args, **kwargs):
|
||
|
|
class TimeLimited(Thread):
|
||
|
|
def __init__(self):
|
||
|
|
Thread.__init__(self)
|
||
|
|
self.error = None
|
||
|
|
self.result = None
|
||
|
|
|
||
|
|
def run(self):
|
||
|
|
self.result = function(*args, **kwargs)
|
||
|
|
|
||
|
|
def stop(self):
|
||
|
|
if self.is_alive():
|
||
|
|
ThreadStop(self)
|
||
|
|
|
||
|
|
t = TimeLimited()
|
||
|
|
t.start()
|
||
|
|
t.join(timeout)
|
||
|
|
if isinstance(t.error, TimeoutException):
|
||
|
|
t.stop()
|
||
|
|
raise TimeoutException('timeout for %s' % (repr(function)))
|
||
|
|
if t.is_alive():
|
||
|
|
t.stop()
|
||
|
|
raise TimeoutException('timeout for %s' % (repr(function)))
|
||
|
|
if t.error is None:
|
||
|
|
return t.result
|
||
|
|
|
||
|
|
return wrapped_function
|
||
|
|
|
||
|
|
return decorator
|