- 論壇徽章:
- 0
|
本帖最后由 wwdwwd 于 2012-04-20 20:23 編輯
摘要:某些進程在結束前必須要處理一些額外的過程才能結束,尤其是數(shù)據(jù)存儲的模塊,進程停止前為保證數(shù)據(jù)的完整性可能要做一些事情,如果發(fā)生段錯誤,這時就需要先截獲segv信號,處理完后再讓程序出core
一般進程收到段錯誤信號默認是dump core文件然后退出,但有些進程在退出時需要處理額外的過程才能結束,這時就不能讓信號執(zhí)行默認的動作了,我們就需要截獲段錯誤信號,然后在信號處理函數(shù)中
處理額外過程,我們稱之為other_function,但是我們處理完后其實還是需要讓程序core出來,以便知道是哪兒出問題了。
基礎知識預備:
1.對線程而言,有三種信號類型:異步信號,同步信號,定向信號。其中異步信號是指傳遞給某些解除了對該信號的阻塞的線程的信號,同步信號是指傳遞給引發(fā)該信號的線程的信號,定向信號是指由pthread_kill函數(shù)發(fā)送給指定線程的信號。像SIGSEGV(段錯誤信號),SIGPFE(浮點錯誤)這樣的錯誤信號就是同步于引發(fā)他們的線程的,因為引發(fā)這些信號的線程將等待信號處理程序處理完成后才能繼續(xù)進行,這樣的信號只能由本線程處理,而其他信號因為不與特定的線程相關,所以他們是異步的,例如其他進程給本進程發(fā)送的信號。如果有幾個線程都解除了對同一個異步信號的阻塞,當有信號到達時,線程運行系統(tǒng)就從中選取一個來處理。
2.對于SIGSEGV信號,如果是由進程段錯誤導致的,則只能設定信號處理函數(shù),不能阻塞或忽略,如果有是由別的進程發(fā)送的,則可以阻塞或忽略。
我們考慮了大概三個方案:
方案1:直接設置信號處理函數(shù),在信號處理函數(shù)中處理other_function,處理完后再signal(SIGSEGV,SIG_DFL),這看起來比較完美,但實際上有鎖的問題。如果出現(xiàn)段錯誤的線程中使用了鎖,在沒有解鎖之前發(fā)生段錯誤,other_function中也使用了同一個鎖,則容易出現(xiàn)死鎖,造成進程hang住。other_function中無鎖時此方案比較簡單易行。
方案2:其他線程阻塞信號,由專有線程處理段錯誤信號。這個不可行,因為我們之前說了,段錯誤信號如果由進程產生則不能被阻塞或忽略
方案3:直接設置信號處理函數(shù),但使用專有線程處理other_function。接到段錯誤信號后調用信號處理函數(shù),信號處理函數(shù)中設置開始處理標記,然后定期檢查專有線程是否處理完,專有線程定期檢查開始處理標記,發(fā)現(xiàn)設定了就開始處理other_function,處理完之后設置處理完標記,然后推出。信號處理函數(shù)中定期檢查處理完標記,發(fā)現(xiàn)一旦被處理完了則再signal(SIGSEGV,SIG_DFL),然后退出,等待出core。
這個方案也會出現(xiàn)方案1中的死鎖問題,但是此時的死鎖是兩個線程之間的死鎖,而不是同一個線程的死鎖,所以是可以處理的,信號處理函數(shù)中設置一個超時時間即可,即信號處理函數(shù)發(fā)現(xiàn)專有線程太久沒有處理完other_function就知道出現(xiàn)死鎖了,這時沒轍了,直接signal(SIGSEGV,SIG_DFL),讓程序出core完事,由于這種可能是比較少的,所以是可以接受的。
另外一個問題是:如果other_function中本身也出core就比較囧了,此時可以在信號處理函數(shù)中做判斷,如果開始處理標記已設定,說明已經已經在處理core了,再進來就直接signal(SIGSEGV,SIG_DFL),讓程序出core了事
說的比較亂,直接看代碼吧- #include <stdint.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <signal.h>
- #include <string.h>
- volatile bool begin_segv_handle=false;
- volatile bool already_handle_other_function=false;
- void segv_handler(int signo);
- void * core_thread(void *args) {
- int i=0;
- while(1) {
- printf("in core thread\n");
- sleep(1);
- if(i++>2) {
- strcpy(NULL,"abc");
- }
- }
- return NULL;
- }
- void * other_function_thread(void *args) {
- int i=0;
- while(1) {
- printf("in other_function_thread\n");
- if(begin_segv_handle) {
- printf("set already_handle_other_function\n");
- already_handle_other_function = true;
- break;
- }
- sleep(1);
- }
- return NULL;
- }
- void segv_handler(int signo) {
- printf("in segv_handler\n");
- if(begin_segv_handle) {
- signal(SIGSEGV,SIG_DFL);
- return ;
- }
- begin_segv_handle = true;
- int i=0;
- while(1) {
- if(i++>10) {
- break;
- }
- if(already_handle_other_function){
- break;
- }
- sleep(1);
-
- }
- signal(SIGSEGV,SIG_DFL);
- }
- int main(void)
- {
- signal(SIGSEGV,segv_handler);
- pthread_t tid_core_thread=0UL,tid_other_function_thread=0UL;
- pthread_create(&tid_core_thread,NULL,core_thread,NULL);
- pthread_create(&tid_other_function_thread,NULL,other_function_thread,NULL);
- pthread_join(tid_core_thread,NULL);
- pthread_join(tid_other_function_thread,NULL);
- return 0;
- }
復制代碼 |
|