This question has been answered before and I'm trying to implement the second solution in the first answer outlined here (NB: the first solution does not concern me, my thread is running a server from an external library and can't be modified to check a flag)
I've tried to implement the simplest case that corresponds to my circumstances. I have a class that spawns a thread and that thread should be stopped externally (the thread never finishes naturally, as in this example). NB: _async_raise
and ThreadWithExc
are copy/pastes of the accepted answer to this question on SO:
import threading
import inspect
import ctypes
import time
# https://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python
def _async_raise(tid, exctype):
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:
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
raise SystemError("PyThreadState_SetAsyncExc failed")
# https://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python
class ThreadWithExc(threading.Thread):
def _get_my_tid(self):
if not self.isAlive():
raise threading.ThreadError("the thread is not active")
if hasattr(self, "_thread_id"):
return self._thread_id
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 raiseExc(self, exctype):
_async_raise( self._get_my_tid(), exctype )
def work():
while True:
print('work')
time.sleep(1)
class Server:
def __init__(self):
self.thread = ThreadWithExc(target=work)
def start(self):
self.thread.start()
def stop(self):
_async_raise(self.thread.raiseExc(TypeError))
server = Server()
server.start()
server.stop()
This gives a ValueError: invalid thread id
exception. I also tried threading.get_ident()
instead of the answer's _get_my_tid()
; that gives me another ID but that one is also invalid.