Python线程死锁不退出,最长运行时间设置TTL, 线程超时杀死线程
import threading import time import inspect import ctypes from queue import Queue class ThreadTTLMonitor(threading.Thread): def __init__(self, threads, ttl=600, delay=0.1, **kwargs): threading.Thread.__init__(self, **kwargs) self.setDaemon(True) self._threads = threads self.delay = delay self.name = 'ThreadMonitor' # self._thread_timer_queue = Queue() for thread in threads: self._thread_timer_queue.put({'thread': thread, 'ttl': ttl}) # self._dismissed = threading.Event() self.start() def create_monitor(self, thread, ttl=600): self._thread_timer_queue.put({'thread': thread, 'ttl': ttl}) @staticmethod def _async_raise(thread_id, exc_type): """raises the exception, performs cleanup if needed""" thread_id = ctypes.c_long(thread_id) if not inspect.isclass(exc_type): exc_type = type(exc_type) res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(exc_type)) if res == 0: raise Exception("invalid thread id") elif res != 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, None) raise Exception("PyThreadState_SetAsyncExc failed") @classmethod def stop_thread(cls, thread): if not thread.is_alive(): return cls._async_raise(thread.ident, Exception) def dismiss(self): """Sets a flag to tell the thread to exit when done with current job. """ self._dismissed.set() def run(self): while True: try: if self._dismissed.isSet(): break item = self._thread_timer_queue.get() if not item: time.sleep(self.delay) continue thread = item.get('thread') ttl = item.get('ttl') ttl -= self.delay if ttl <= 0: self.stop_thread(thread) continue item.update(ttl=ttl) self._thread_timer_queue.put(item) except Exception as e: raise e time.sleep(self.delay)