優雅處理段錯誤

2021-09-22 21:52:05 字數 2149 閱讀 3226

摘要:某些程序在結束前必須要處理一些額外的過程才能結束,尤其是資料儲存的模組,程序停止前為保證資料的完整性可能要做一些事情,如果發生段錯誤,這時就需要先截獲se**訊號,處理完後再讓程式出core

一般程序收到段錯誤訊號預設是dump core檔案然後退出,但有些程序在退出時需要處理額外的過程才能結束,這時就不能讓訊號執行預設的動作了,我們就需要截獲段錯誤訊號,然後在訊號處理函式中

處理額外過程,我們稱之為other_function,但是我們處理完後其實還是需要讓程式core出來,以便知道是哪兒出問題了。

基礎知識預備:

1.對執行緒而言,有三種訊號型別:非同步訊號,同步訊號,定向訊號。其中非同步訊號是指傳遞給某些解除了對該訊號的阻塞的執行緒的訊號,同步訊號是指傳遞給引發該訊號的執行緒的訊號,定向訊號是指由pthread_kill函式傳送給指定執行緒的訊號。像sigse**(段錯誤訊號),sigpfe(浮點錯誤)這樣的錯誤訊號就是同步於引發他們的執行緒的,因為引發這些訊號的執行緒將等待訊號處理程式處理完成後才能繼續進行,這樣的訊號只能由本執行緒處理,而其他訊號因為不與特定的執行緒相關,所以他們是非同步的,例如其他程序給本程序傳送的訊號。如果有幾個執行緒都解除了對同乙個非同步訊號的阻塞,當有訊號到達時,執行緒執行系統就從中選取乙個來處理。

2.對於sigse**訊號,如果是由程序段錯誤導致的,則只能設定訊號處理函式,不能阻塞或忽略,如果有是由別的程序傳送的,則可以阻塞或忽略。

我們考慮了大概三個方案:

方案1:直接設定訊號處理函式,在訊號處理函式中處理other_function,處理完後再signal(sigse**,sig_dfl),這看起來比較完美,但實際上有鎖的問題。如果出現段錯誤的執行緒中使用了鎖,在沒有解鎖之前發生段錯誤,other_function中也使用了同乙個鎖,則容易出現死鎖,造成程序hang住。other_function中無鎖時此方案比較簡單易行。

方案2:其他執行緒阻塞訊號,由專有執行緒處理段錯誤訊號。這個不可行,因為我們之前說了,段錯誤訊號如果由程序產生則不能被阻塞或忽略

方案3:直接設定訊號處理函式,但使用專有執行緒處理other_function。接到段錯誤訊號後呼叫訊號處理函式,訊號處理函式中設定開始處理標記,然後定期檢查專有執行緒是否處理完,專有執行緒定期檢查開始處理標記,發現設定了就開始處理other_function,處理完之後設定處理完標記,然後推出。訊號處理函式中定期檢查處理完標記,發現一旦被處理完了則再signal(sigse**,sig_dfl),然後退出,等待出core。

這個方案也會出現方案1中的死鎖問題,但是此時的死鎖是兩個執行緒之間的死鎖,而不是同乙個執行緒的死鎖,所以是可以處理的,訊號處理函式中設定乙個超時時間即可,即訊號處理函式發現專有執行緒太久沒有處理完other_function就知道出現死鎖了,這時沒轍了,直接signal(sigse**,sig_dfl),讓程式出core完事,由於這種可能是比較少的,所以是可以接受的。

另外乙個問題是:如果other_function中本身也出core就比較囧了,此時可以在訊號處理函式中做判斷,如果開始處理標記已設定,說明已經已經在處理core了,再進來就直接signal(sigse**,sig_dfl),讓程式出core了事

說的比較亂,直接看**吧

#include

#include

#include

#include

#include

#include

#include

volatile bool begin_se**_handle=false;

volatile bool already_handle_other_function=false;

void se**_handler(int signo);

void * core_thread(void *args)

}return null;

}void * other_function_thread(void *args)

sleep(1);

}return null;

}void se**_handler(int signo)

begin_se**_handle = true;

int i=0;

while(1)

if(already_handle_other_function)

sleep(1);

}signal(sigse**,sig_dfl);

}int main(void)

如何優雅的處理錯誤

1 封裝錯誤error,使其記錄錯誤檔名稱 檔案路徑 行數 操作 錯誤資訊等相關資訊。封裝錯誤型別,myerror 型別記錄了檔案,行號,相關的錯誤資訊 type myerror struct patherror 除了底層錯誤外還提供了使用哪個檔案,執行哪個操作等相關資訊。type patherro...

段錯誤?打的就是段錯誤!!

呵,段錯誤?自從我看了這篇文章,我還會怕你個小小段錯誤?請開啟你的linux終端,跟緊咯,準備發車!嘟嘟嘟噠 include void errfunc intmain 這段 拿去執行,肯定段錯誤。系統會在程式崩潰的那一剎那將整個核心的資訊記錄在乙個檔案裡邊。如果你是第一次,那麼ls是查不到的。這樣 ...

段錯誤總結

sigsegv是在訪問記憶體時發生的錯誤,它屬於記憶體管理的範疇 sigsegv是乙個使用者態的概念,是作業系統在使用者態程式錯誤訪問記憶體時所做出的處理。當使用者態程式訪問 訪問表示讀 寫或執行 不允許訪問的記憶體時,產生sigsegv。當使用者態程式以錯誤的方式訪問允許訪問的記憶體時,產生sig...