I tried to cancel thread with c-function pthread_cancel(). Also I check canceltype and cancelstate: it has default values: PTHREAD_CANCEL_DEFERRED and PTHREAD_CANCEL_ENABLE
import threading
import ctypes
from time import sleep
import os
import sys
libc = ctypes.CDLL("libc.so.6")
pthread_t = ctypes.c_ulong
PTHREAD_CANCEL_DEFERRED = 0
PTHREAD_CANCEL_ASYNCHRONOUS = 1
canceltype = ctypes.c_int
pthread_setcanceltype = libc.pthread_setcanceltype
pthread_setcanceltype.argtypes = [ctypes.c_int, ctypes.POINTER(canceltype)]
pthread_setcanceltype.restype = ctypes.c_int
PTHREAD_CANCEL_ENABLE = 0
PTHREAD_CANCEL_DISABLE = 1
cancelstate = ctypes.c_int
pthread_setcancelstate = libc.pthread_setcancelstate
pthread_setcancelstate.argtypes = [ctypes.c_int, ctypes.POINTER(cancelstate)]
pthread_setcancelstate.restype = ctypes.c_int
pthread_cancel = libc.pthread_cancel
pthread_cancel.argtypes = [pthread_t]
pthread_cancel.restype = ctypes.c_int
def terminate_thread(thread):
if not thread.is_alive():
return
#exc = ctypes.py_object(SystemExit)
#res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread.ident), exc)
res = pthread_cancel(thread.ident)
#if res == 0:
# raise ValueError("Can't stop thread.")
if res != 0:
#ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
raise SystemError("Error while stopping thread:",res)
def thread2():
prev_type = canceltype()
ret = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, ctypes.byref(prev_type))
if ret != 0:
err = ctypes.get_errno()
print(f"pthread_setcanceltype failed: errno={err}")
return
print('prev_type=',prev_type)
ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, ctypes.byref(prev_type))
if ret != 0:
err = ctypes.get_errno()
print(f"pthread_setcancelstate failed: errno={err}")
return
print('prev_state=',prev_type)
print("thread2 start reading")
#input()
sleep(1000) # for sleep() and for input() it behaves the same
print("thread2 ends")
thr2 = threading.Thread(target=thread2)
thr2.start()
sleep(2)
print("killing thr2")
terminate_thread(thr2)
thr2.join()
print("main exit")
Why this code stuck in thr2.join() with output:
prev_type= c_int(0)
prev_state= c_int(0)
thread2 start reading
killing thr2
But this code:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void * thread2(void *){
printf("thread2 start reading\n");
getchar();
printf("thread2 ends\n");
}
int main(){
printf("PTHREAD_CANCEL_DEFERRED = %d\nPTHREAD_CANCEL_ASYNCHRONOUS = %d\nPTHREAD_CANCEL_ENABLE = %d\nPTHREAD_CANCEL_DISABLE = %d\n",
PTHREAD_CANCEL_DEFERRED,PTHREAD_CANCEL_ASYNCHRONOUS,PTHREAD_CANCEL_ENABLE,PTHREAD_CANCEL_DISABLE);
pthread_t thr2;
pthread_create(&thr2, NULL, thread2, NULL);
sleep(2);
printf("killing thr2\n");
pthread_cancel(thr2);
pthread_join(thr2, NULL);
printf("main exit\n");
}
normally treat cancellation of thread? With output:
PTHREAD_CANCEL_DEFERRED = 0
PTHREAD_CANCEL_ASYNCHRONOUS = 1
PTHREAD_CANCEL_ENABLE = 0
PTHREAD_CANCEL_DISABLE = 1
thread2 start reading
killing thr2
main exit
sleep(), read() - is cancellation points
Even if I set PTHREAD_CANCEL_ASYNCHRONOUS at the beginning of thread and remove htr2.join() at the end of program, the program continues to hang.
UPD
I found error: I should use thread.native_id instead thread.ident. And as result I get segmentation fault as expected.