如果我們在FreeBSD或Mac OS X上執行相同的程式,我們會發現該程式會導致段錯誤。發生這種情況是因為在這些系統上,pthread_cleanup_push實現為在堆疊上儲存某些上下文的宏。當執行緒1在對pthread_cleanup_push的呼叫和對pthread_cleanup_pop的呼叫之間返回時,堆疊被覆蓋,並且這些平臺在呼叫清理處理程式時嘗試使用此(已損壞的)上下文。在Single UNIX Specification中,在對pthread_cleanup_push和pthread_cleanup_pop的一對匹配呼叫之間返回會導致未定義的行為。在這兩個函式之間返回的唯一可移植方法是呼叫pthread_exit。
回答這個問題,首先得搞清楚執行緒關閉或者退出有哪些方式
執行緒的退出方式如果程序中的任何執行緒呼叫exit,_Exit或_exit,則整個程序終止。 類似地,當訊號的預設操作是終止程序時,傳送到執行緒的訊號將終止整個程序。單個執行緒可以有三種方式退出其控制流程,而不會終止整個程序。1執行緒可以簡單地從執行緒處理程式中返回,返回值是執行緒的退出程式碼。2該執行緒可以被同一程序中的另一個執行緒取消。3該執行緒可以呼叫pthread_exi執行緒退出的返回值#include <pthread.h> void pthread_exit(void *rval_ptr);#include <pthread.h> int pthread_join(pthread_t thread, void **rval_ptr);pthread_join函式的rval_ptr引數是無型別指標。程序中的其他執行緒可透過呼叫pthread_join函式來使用rval_ptr指標,呼叫它執行緒將阻塞,直到指定的執行緒呼叫pthread_exit或從其執行緒處理程式中返回或被取消。如果只是從其執行緒處理程式返回,則rval_ptr將包含返回碼。如果執行緒被取消,則rval_ptr指定的記憶體位置設定為PTHREAD_CANCELED。
透過呼叫pthread_join,自動會將加入的執行緒放置在分離狀態,如果執行緒已處於分離狀態,則pthread_join可能會失敗,返回EINVAL。如果我們對執行緒的返回值不感興趣,我們可以將rval_ptr設定為NULL。在這種情況下,呼叫pthread_join允許我們等待指定的執行緒,但不去檢索執行緒的終止狀態。
下圖顯示瞭如何從已終止的執行緒中獲取退出程式碼
執行結果:
lj@lj-PC:~$ ./ptest
thread 1 returning
thread 2 exiting
thread 1 exit code 1
thread 2 exit code 2
執行緒如何取消一個執行緒可以透過呼叫pthread_cancel函式請求取消同一程序中的另一個。
#include <pthread.h> int pthread_cancel(pthread_t tid);在預設情況下,pthread_cancel將使tid指定的執行緒的行為就像它使用PTHREAD_CANCELED引數呼叫pthread_exit一樣。 但是,執行緒可以選擇忽略或以其他方式控制取消的方式。 請注意,pthread_cancel不會等待執行緒終止。
執行緒可以安排函式在退出時被呼叫,這些函式稱為執行緒清理處理程式。 可以為一個執行緒建立多個清理處理程式。 處理程式記錄在堆疊中,這意味著它們的執行順序與它們註冊的順序相反。
#include <pthread.h> void pthread_cleanup_push(void (*rtn)(void *), void *arg);void pthread_cleanup_pop(int execute);當執行緒執行以下操作之一時,pthread_cleanup_push函式會被呼叫
呼叫pthread_exit
回覆取消請求
使用非零執行引數呼叫pthread_cleanup_pop
下圖舉例如何使用執行緒清理處理程式。
執行結果:
lj@lj-PC:~$ ./pclean
thread 1 start
thread 1 push complete
thread 2 start
thread 1 exit code 1
thread 2 push complete
cleanup: thread 2 second handler
cleanup: thread 2 first handler
thread 2 exit code 2
從輸出中,我們可以看到兩個執行緒都正常啟動並退出,但只調用了第二個執行緒的清理處理程式。因此,如果執行緒是透過其處理函式直接返回而終止,則不會呼叫其清理處理程式,不過此行為在具體平臺實現之間會有所不同。另請注意,清理處理程式的呼叫順序與安裝它們的順序相反。
如果我們在FreeBSD或Mac OS X上執行相同的程式,我們會發現該程式會導致段錯誤。發生這種情況是因為在這些系統上,pthread_cleanup_push實現為在堆疊上儲存某些上下文的宏。當執行緒1在對pthread_cleanup_push的呼叫和對pthread_cleanup_pop的呼叫之間返回時,堆疊被覆蓋,並且這些平臺在呼叫清理處理程式時嘗試使用此(已損壞的)上下文。在Single UNIX Specification中,在對pthread_cleanup_push和pthread_cleanup_pop的一對匹配呼叫之間返回會導致未定義的行為。在這兩個函式之間返回的唯一可移植方法是呼叫pthread_exit。
執行緒和程序的類似操作從上文我們可以看到執行緒和程序的相似之處,見如下表格:
講了這麼多,還有好多細節沒有講到,只要詳細的瞭解了這些細節,我相信關於你的這個問題“linux下C中怎麼讓才能安全關閉執行緒”自然就有了答案。