mirror of
https://github.com/clearml/clearml
synced 2025-02-01 09:36:49 +00:00
63 lines
1.7 KiB
Python
63 lines
1.7 KiB
Python
import ctypes
|
|
import threading
|
|
import sys
|
|
import time
|
|
|
|
|
|
# Nasty hack to raise exception for other threads
|
|
def _lowlevel_async_raise(thread_obj, exception=None):
|
|
NULL = 0
|
|
found = False
|
|
target_tid = 0
|
|
for tid, tobj in threading._active.items():
|
|
if tobj is thread_obj:
|
|
found = True
|
|
target_tid = tid
|
|
break
|
|
|
|
if not found:
|
|
# raise ValueError("Invalid thread object")
|
|
return False
|
|
|
|
if not exception:
|
|
exception = SystemExit()
|
|
|
|
if sys.version_info.major >= 3 and sys.version_info.minor >= 7:
|
|
target_tid = ctypes.c_ulong(target_tid)
|
|
NULL = ctypes.c_ulong(NULL)
|
|
else:
|
|
target_tid = ctypes.c_long(target_tid)
|
|
NULL = ctypes.c_long(NULL)
|
|
|
|
try:
|
|
ret = ctypes.pythonapi.PyThreadState_SetAsyncExc(target_tid, ctypes.py_object(exception))
|
|
except:
|
|
ret = 0
|
|
|
|
# ref: http://docs.python.org/c-api/init.html#PyThreadState_SetAsyncExc
|
|
if ret == 0:
|
|
# raise ValueError("Invalid thread ID")
|
|
return False
|
|
elif ret > 1:
|
|
# Huh? Why would we notify more than one threads?
|
|
# Because we punch a hole into C level interpreter.
|
|
# So it is better to clean up the mess.
|
|
try:
|
|
ctypes.pythonapi.PyThreadState_SetAsyncExc(target_tid, NULL)
|
|
except:
|
|
pass
|
|
# raise SystemError("PyThreadState_SetAsyncExc failed")
|
|
return False
|
|
|
|
# print("Successfully set asynchronized exception for", target_tid)
|
|
return True
|
|
|
|
|
|
def kill_thread(thread_obj, wait=False):
|
|
if not _lowlevel_async_raise(thread_obj, SystemExit()):
|
|
return False
|
|
|
|
while wait and thread_obj.is_alive():
|
|
time.sleep(0.1)
|
|
return True
|