[Linux/C++] 用 signal handler 處理 segmentation fault 並產生 core dump

[Linux/C++] 用 signal handler 處理 segmentation fault 並產生 core dump

專案裡有個程式不太穩定,偶爾會 crash,

一般來說它就是系統自動產生 core dump 了~

但我們想要在這種情況下,還可以做一些處理,像是顯示出掛掉的 thread ID 之類的…

 

在網路上找到了 How to handle SIGSEGV, but also generate a core dump 這篇文章,

也順利的依照類似的方式達成需求了,

下面是個範例,差別在於我是用 sigaction() 而不是 signal()。

 

 1. 首先要設定 signal handler

通常是在程式開始的地方設定,不然 signal 發生時還沒設定好,就接不到了。

像我的程式是一個 library 的話,就要先定義 library load 和 unload 時要執行的函式: 

// Define DLL onload and onunload functions
void __attribute__ ((constructor)) MyLibOnLoad();
void __attribute__ ((destructor)) MyLibOnUnLoad();

 

 接著在 load 函式中,設定 signal handler。

下面的範例中我們抓了 SIGBUS 和 SIGSEGV 這兩種常見的 crash signal:

void MyLibOnLoad()
{
// Register signal handler for following signals:
//   SIGBUS:  Bus error (bad memory access)
//   SIGSEGV: Invalid memory reference
// Here sigaction() is used instead of signal() to block other signals
//  until current signal returns.
struct sigaction sa = {};
memset(&sa, 0, sizeof(struct sigaction));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = MyLibCrashHandler;
sa.sa_flags = SA_SIGINFO|SA_RESETHAND;  // Reset signal handler to system default after signal triggered
sigaction(SIGBUS, &sa, NULL);
sigaction(SIGSEGV, &sa, NULL);
}

 

要注意的是,我們在 sa_flags 中,有設定 SA_RESETHAND,

所以在 signal 處理之後,signal handler 會被重設成系統預設值,

這樣才有機會讓系統預設的行為(產生 core dump)執行。

 

2. 處理 signal

當 signal SIGBUS/SIGSEGV 發生之後,我們設定的 signal handler 就會被呼叫到。

我們可以在這裡對這錯誤做一些處理。

但因為這是 crash,所以通常我們不會做太複雜耗時的工作(有可能會被系統強制停掉)。

在下面的範例中是將 crash 的 thread ID 寫到一個檔案去: 

void MyLibCrashHandler(int nSignal, siginfo_t* si, void* arg)
{
// Get thread id
pid_t nThreadID = syscall(SYS_gettid);
// Write thread id into a file
FILE* pf = fopen("crash_thread_id", "wt");
if (pf != NULL)
{
fprintf(pf, "%d\n", nThreadID);
fclose(pf);
}
// Send self the same signal again, so that default system signal handler is invoked,
//   which will generate core dump files.
kill(getpid(), nSignal);
}

 

上面程式的最後部分,用 kill 送給自己同一個 signal。

因為我們之前已經將 sa_flags 設定為 SA_RESETHAND,

所以這第二個 signal 會被系統處理,而不是用我們定義的 signal handler,

因此系統就會依循預設行為,產生 core dump 囉~

 

 

 

//
//

(本頁面已被瀏覽過 427 次)

發表迴響

你的電子郵件位址並不會被公開。

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料