在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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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文件的。
参考
http://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的信息