Chris Craik | b2cbf15 | 2015-07-28 16:26:29 -0700 | [diff] [blame^] | 1 | """ |
| 2 | Kill a thread, from http://sebulba.wikispaces.com/recipe+thread2 |
| 3 | """ |
| 4 | import six |
| 5 | try: |
| 6 | import ctypes |
| 7 | except ImportError: |
| 8 | raise ImportError( |
| 9 | "You cannot use paste.util.killthread without ctypes installed") |
| 10 | if not hasattr(ctypes, 'pythonapi'): |
| 11 | raise ImportError( |
| 12 | "You cannot use paste.util.killthread without ctypes.pythonapi") |
| 13 | |
| 14 | def async_raise(tid, exctype): |
| 15 | """raises the exception, performs cleanup if needed. |
| 16 | |
| 17 | tid is the value given by thread.get_ident() (an integer). |
| 18 | Raise SystemExit to kill a thread.""" |
| 19 | if not isinstance(exctype, (six.class_types, type)): |
| 20 | raise TypeError("Only types can be raised (not instances)") |
| 21 | if not isinstance(tid, int): |
| 22 | raise TypeError("tid must be an integer") |
| 23 | res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(exctype)) |
| 24 | if res == 0: |
| 25 | raise ValueError("invalid thread id") |
| 26 | elif res != 1: |
| 27 | # """if it returns a number greater than one, you're in trouble, |
| 28 | # and you should call it again with exc=NULL to revert the effect""" |
| 29 | ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), 0) |
| 30 | raise SystemError("PyThreadState_SetAsyncExc failed") |