一、概念说明
在程序崩溃的时候,我们将会获取到两个信息:
• signal: 信号量,下文将会详细的说明不同的信号量及其含义
• code: 错误码, 除了几个所有信号量(signal) 公共的错误码(code),一般不同信号量(signal)有特定的错误码(code),可以看做是信号量(signal)的补充说明。
二、信号量(signal) 和 错误码(code)说明
本节只介绍与崩溃相关的几个 signal(CrashSDK 捕获的 signal)及相关 code 的说明,更多内容见后面的参考文献或网上找资料了解。
1. SIGILL
SIG是信号名的通用前缀,ILL是 illegal instruction( 非法指令 ) 的缩写。
对应的数值为 4。
SIGILL 是当一个进程尝试执行一个非法指令时发送给它的信号。
常见原因有:
- CPU架构不匹配
- .so 文件被破坏,或者代码段被破坏导致;
- 主动崩溃,如 _builtintrap() 也会使用非法指令来实现。
si_addr 为出错的指令。
该信号量中常见的错误码说明:
Code | 说明 |
---|---|
ILL_ILLOPC | 非法的操作码(opcode) |
ILL_ILLOPN | 非法的操作数(operand) |
ILL_ILLADR | 非法的寻址模式 |
ILL_ILLTRP | 非法的trap |
ILL_PRVOPC | 特权操作码(Privileged opcode) |
ILL_PRVREG | 特权寄存器(Privileged register) |
ILL_COPROC | 协处理器错误 |
ILL_BADSTK | 内部堆栈错误 |
2. SIGBUS
SIG是信号名的通用前缀,BUS是bus error (总线错误 ) ,意味着系统检测到硬件问题后发送给进程的信号。
对应的数值为7。
通常该信号的产生不是因为硬件有物理上的损坏,而是代码实现有 bug 导致 ,如地址不对齐,或者不存在的物理地址等。
si_addr 为所访问的非法地址。
该信号量中常见的错误码说明:
Code | 说明 |
---|---|
BUS_ADRALN | 访问的地址不对齐。32位处理器一般要求指针是4字节对齐的 |
BUS_ADRERR | 访问不存在的物理地址。一般是由于 mmap 的文件发生 truncated 导致。常见于文件访问过程中,被删除或者替换;或 mmap 到内存后,继续向文件写入且导致文件 truncated,再读取时就会出现该错误;另外, mmap 且访问超过文件实际大小的空间时,也可能会出现该错误 |
BUS_OBJERR | 特定对象的硬件错误 |
BUS_MCEERR_AR | BUS_MCEERR_AR |
BUS_MCEERR_AQ | BUS_MCEERR_AQ |
3. SIGSEGV
SIG 是信号名的通用前缀, SEGV 是 segmentation violation 的缩写。
对应的数值为 11。
该信号意味着一个进程执行了一个无效的内存引用,或发生段错误。
si_addr 为所访问的无效地址。
该信号量中常见的错误码说明:
Code | 说明 |
---|---|
SEGV_MAPERR | 地址不在 /proc/self/map 映射中 |
SEGV_ACCERR | 没有访问权限 |
4. SIGFPE
SIG是信号名的通用前缀。FPE是floating-point exception(浮点异常)的首字母缩写拼接而成。
对应的数值为 8。
该信号一般是算术运算相关问题导致的。
si_addr 为失败的指令。
该信号量中常见的错误码说明:
Code | 说明 |
---|---|
FPE_INTDIV | 整数除以 0 |
FPE_INTOVF | 整数溢出 |
FPE_FLTDIV | 浮点数除以 0 |
FPE_FLTOVF | 浮点数向下溢出 |
FPE_FLTRES | 浮点数结果不精确 |
FPE_FLTINV | 无效的浮点运算 |
FPE_FLTSUB | 下标超出范围 |
5. SIGABRT
SIG是信号名的通用前缀。ABRT是abort program的缩写。
对应的数值为 6。
该信号意味着异常退出;通常是调用 abort(), raise(), kill(), pthread_kill() 或者被系统进程杀死时出现。
当错误码为 SI_USER 时表示是被其它程序杀死,一般情况是由于ANR被 system_server 杀死;
其他错误码一般是业务自己调用 abort() 等函数退出,此时错误码一般认为无效。
6. SIGSTKFLT
SIG是信号名的通用前缀,STKFLT是stack fault 的缩写。
对应的数值为 16。
按照官方文档说明,该信号量意味着协处理器栈故障。
根据网上的部分问题结论说明,在内存耗尽时,一般 malloc 返回 NULL 且设置 errno 为 ENOMEM,但有些系统可能会使用 SIGSTKFLT 信号代替。
7. SIGPIPE
该信号对应的数值为 13。
该信号意味着管道错误,通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止仍继续往管道写,写进程就会收到 SIGPIPE 信号。
8. SIGUSR2
为 12。用户自定义信号2。
9. SIGTERM
SIG是信号名的通用前缀,TERM 是 Termination 的缩写。该信号对应的数值为 15。
与 SIGKILL (signal 9) 类似,不过 SIGKILL 不可捕获,而 SIGTERM 可被捕获。一般常见于 APP 处于后台时,被系统 vold 进程使用 SIGTERM 杀死,该情形基本没有意义,可忽略。
另外,chromium 多进程架构中,经常也会使用 SIGTERM 杀死出现了异常的子进程。
10. SIGSYS
该信号对应的数值为 31,通常是因为无效的 linux 内核系统调用而产生。
在 android O (android 8.0) 中,部分不安全的系统调用被移除,若代码中仍然使用它们,则会出现 SIGSYS。
11. SIGTRAP
该信号对应的数值为 5。gdb 调试设置断点等操作使用的信号。
Code | 说明 |
---|---|
TRAP_BRKPT | TRAP_BRKPT |
TRAP_TRACE | TRAP_TRACE |
TRAP_BRANCH | TRAP_BRANCH |
TRAP_HWBKPT | TRAP_HWBKPT |
其他的信号对应的数值如下
参考文献:
- siginfo_t — data structure containing signal information
- linux系统编程之信号(一):中断与信号
- linux系统编程之信号(六):信号发送函数sigqueue和信号安装函数sigaction
- SIGSTKFLT