線程取消的方法是向目标線程發Cancel信号,但如何處理Cancel信号則由目标線程自己決定,或者忽略、或者立即終止、或者繼續運作至Cancelation-point(取消點),由不同的Cancelation狀态決定。
線程接收到CANCEL信号的預設處理(即pthread_create()建立線程的預設狀态)是繼續運作至取消點,也就是說設定一個CANCELED狀态,線程繼續運作,隻有運作至Cancelation-point的時候才會退出。
(1)什麼是線程取消點
根據POSIX标準,pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函數以及read()、write()等會引起阻塞的系統調用都是Cancelation-point,而其他pthread函數都不會引起Cancelation動作。但是pthread_cancel的手冊頁聲稱,由于LinuxThread庫與C庫結合得不好,因而目前C庫函數都不是Cancelation-point;但CANCEL信号會使線程從阻塞的系統調用中退出,并置EINTR錯誤碼,是以可以在需要作為Cancelation-point的系統調用前後調用pthread_testcancel(),進而達到POSIX标準所要求的目标,即如下代碼段:
pthread_testcancel();
retcode = read(fd, buffer, length);
(2)與線程取消相關的pthread函數
int pthread_cancel(pthread_t thread)
發送終止信号給thread線程,如果成功則傳回0,否則為非0值。發送成功并不意味着thread會終止。
int pthread_setcancelstate(int state, int *oldstate)
設定本線程對Cancel信号的反應,state有兩種值:PTHREAD_CANCEL_ENABLE(預設)和PTHREAD_CANCEL_DISABLE,分别表示收到信号後設為CANCLED狀态和忽略CANCEL信号繼續運作;old_state如果不為NULL則存入原來的Cancel狀态以便恢複。
int pthread_setcanceltype(int type, int *oldtype)
設定本線程取消動作的執行時機,type由兩種取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,僅當Cancel狀态為Enable時有效,分别表示收到信号後繼續運作至下一個取消點再退出和立即執行取消動作(退出);oldtype如果不為NULL則存入運來的取消動作類型值。
void pthread_testcancel(void)
Calling pthread_testcancel() creates a cancellation point within the calling thread, so that a thread that is otherwise executing code that contains no cancellation points will respond to a cancellation request.
If cancelability is disabled (using pthread_setcancelstate(3)), or no cancellation request is pending, then a call to pthread_cancel(3) has no effect.
也就是說pthread_testcancel在不包含取消點,但是又需要取消點的地方建立一個取消點,以便在一個沒有包含取消點的執行代碼線程中響應取消請求。
示例代碼【3】

View Code
示例代碼跟蹤

參考: