diff -r 20c41a7e2173 -r 83b28fc0d731 web/ldt/utils/threading.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/ldt/utils/threading.py Mon Dec 13 23:55:19 2010 +0100 @@ -0,0 +1,44 @@ +import threading +import inspect +import ctypes + +def _async_raise(tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + raise TypeError("Only types can be raised (not instances)") + 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, 0) + raise SystemError("PyThreadState_SetAsyncExc failed") + + +class Thread(threading.Thread): + def _get_my_tid(self): + """determines this (self's) thread id""" + if not self.isAlive(): + raise threading.ThreadError("the thread is not active") + + # do we have it cached? + if hasattr(self, "_thread_id"): + return self._thread_id + + # no, look for it in the _active dict + for tid, tobj in threading._active.items(): + if tobj is self: + self._thread_id = tid + return tid + + raise AssertionError("could not determine the thread's id") + + def raise_exc(self, exctype): + """raises the given exception type in the context of this thread""" + _async_raise(self._get_my_tid(), exctype) + + def terminate(self): + """raises SystemExit in the context of the given thread, which should + cause the thread to exit silently (unless caught)""" + self.raise_exc(SystemExit)