一次没有转储的问题排查
一个运行好好地程序,突然在某个凌晨挂掉了, 由于系统没有配置ulimit -c unlimited 。所有没有CORE 文件出来。
- 首先排查是否人为停止了程序
查看后台日志,日志打印信息截止到23:00:04 , 在这么晚的时间应该没有人还特么加班。并且还停止程序。
使用history 命令看看操作记录,也确实没有可疑的操作。排除人为干扰。 - 排查在23点的时候,程序有没有什么其他的动作。比如日志备份,数据备份。程序自检等。
询问相关运维人员,23 点程序没有什么特殊的动作。再说程序每天都跑的好好地,怎么突然就挂了呢。排除 -
查看系统环境
查看程序常用的系统资源是否有异常
image.png
从图中可以看到,8G 内存,已经使用了6.6G 还剩余1.1G cached缓存了2.6G 。并且居然连交换分区都用了130M
为啥cached 能缓存了这么多。cached 多说明有进程在大量读文件。应该有进程再大量操作数据库,但不是咱们程序引起的,先不管他,以后再排查这个问题。
至少内存还有1.1G 咱们程序不至于被OOM , 排除
-
查看系统日志
经过以上排除,只有看看系统日志有没有什么有价值的信息,用dmesg 查看
image.png
从系统日志看,进程3294 段错误了,段错误地址0xfffffffffffffff9 , 取指地址0x00007f5f4c6fc094 堆栈地址0x00007fff94d859d0
出错库libstdc++.so.6.0.20 ,库的加载基指为0x7f5f4c637000 ,在库文件中的偏移地址0xf3000
错误码4 ,参考如下
bit2:值为1表示是用户态程序内存访问越界,值为0表示是内核态程序内存访问越界
bit1: 值为1表示是写操作导致内存访问越界,值为0表示是读操作导致内存访问越界
bit0: 值为1表示没有足够的权限访问非法地址的内容,值为0表示访问的非法地址根本没有对应的页面,也就是无效地址
错误码4 刚好表示用户态内存访问越界。
从上述信息看,进程3294 在地址0xfffffffffffffff9 发生的系统调用。在执行libstdc++.so.6.0.20 中偏移量在0xf3000 之后的某一条指令挂了。
我们用 0x00007f5f4c6fc094 - 0x7f5f4c637000 = C5094 。
可定位到在出错指令在库libstdc++.so.6.0.20 中偏移量0xf3000处 ,再往后偏移0xC5094 个指令地址 为0x1B8094
反汇编库libstdc++.so.6.0.20 将库中符号导出到文件
objdump -tT libstdc++.so.6.0.20 >> testxx.txt
image.png
这不是异常处理么,没法看到是谁引起的异常啊
用addr2line 反汇编试试(-f 表示显示函数信息, -e 指定可执行文件)
addr2line -f -e libstdc++.so.6.0.20 f3000
image.png
啥都看不到。我以为只要定位到库中哪个函数产生了异常,然后再代码中搜索调用函数的位置,就可以定位到问题了,看样子,是我太年轻了。