在Android 開發中遇到一些signal 的情況,簡要總結如下:
1)Zygote 監控 子進程的退出情況
jellybean/dalvik/vm/native/dalvik_system_Zygote.cpp#151
151 sa.sa_handler = sigchldHandler;
153 err = sigaction (SIGCHLD, &sa, NULL);
當進程結束的時候,log 中有類似下面的消息,這就是 Zygote打印出來,它會報告子進程被什麼 signal 終結的
D Zygote : Process 749 terminated by signal (11)
2)DVM 生成單獨的信號處理線程,用來對三個信號做特殊處理:
每個進程包含多個線程,當進程受到 signal 的時候,可能被其中任何一個線程處理
一個應用運行在虛擬機上dvm上一個應用也是一個dvm 進程,dvm 專門創建瞭一個信號處理線程來處理這3個信號,其他的線程都要block對這三個信號的處理。
這三個信號是 SIGQUIT, SIGUSR1, SIGUSR2, 看下面代碼,後面兩個信號 vm 內部要使用
dalvik/vm/Init.cpp
static void blockSignals() { sigset_t mask; int cc; sigemptyset(&mask); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGUSR1); // used to initiate heap dump #if defined(WITH_JIT) && defined(WITH_JIT_TUNING) sigaddset(&mask, SIGUSR2); // used to investigate JIT internals #endif //sigaddset(&mask, SIGPIPE); cc = sigprocmask(SIG_BLOCK, &mask, NULL); assert(cc == 0); }
為何處理 quit
Android 應用在收到異常終止信號(SIGQUIT)時,沒有遵循傳統 UNIX信號模型的默認行為 (終止 + core )。而是打印出trace 文件來,以利於記錄應用異常終止的原因。
Trace文件是 android davik 虛擬機在收到異常終止信號 (SIGQUIT)時產生的。 最經常的觸發條件是 android應用中產生瞭 FC (force close)。由於是該文件的產生是在 DVM裡,所以隻有運行 dvm實例的進程(如普通的java應用,java服務等)才會產生該文件,android 本地應用 (native app,指 運行在 android lib層,用c/c++編寫的linux應用、庫、服務等)在收到 SIGQUIT時是不會產生 trace文件的。
參考
https://blog.csdn.net/rambo2188/article/details/7017241
3) 其他基於 bionic 的應用,都被 Android 動瞭手腳
android的實現是在 main 運行之前 先運行 debugger_init 方法,以實現攔截系統異常的幾個singal:SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV和SIGPIPE, 代碼位於: bionic/linker/debugger.c, 把 debugger_init 註入 是通過在 linker 中做手腳 (bionic/linker/linker.c#2255)
而後當程序收到那幾個信號後,不是安裝 linux 缺省的處理方法,而是運行 debugger_init 中設定的信號處理方法,此方法就是和 debuggerd (守護進程)通信,通過socket告訴其 tid ,
而後 debuggerd 通過調用
tid_attach_status= ptrace(PTRACE_ATTACH, tid, 0, 0);
這裡,debuggerd就掛上ptrace瞭,attach到出問題的線程,debuggerd進程就是被調試進程的父進程瞭,這樣debuggerd就可以控制tid線程瞭,最終生成 tomestone的信息