在挂机测试过程中,出现了signal 11错误。
编译时加入-g,去掉strip后,使用gdb运行,挂机多次一直不再出现。可能是gdb运行与全速跑还是有些区别。
既然直接gdb运行不能复现问题,只能在全速跑时产生core dump文件事后分析了。
首先在程序中不能注册信号捕捉,否则当发生异常时,会进入注册的信号捕捉处理内,造成系统不产生core dump文件。
编译时加入-g,strip尽量去掉。
可以在程序中加入ulimit -c unlimited。
程序中加入core dump转存路径,当出现异常时保存core dump文件路径echo /data/coredump/core.%e.%p.%s.%t> /proc/sys/kernel/core_pattern。
参考:
Linux环境崩溃生成core文件以及调试 - 恋恋风辰 - 博客园
Linux Core 文件在系统排障中的应用_Linux教程_Linux公社-Linux系统门户网站
程序挂机后,获取到了core dump文件,该core dump文件名中有出现问题异常时的线程名字。
使用gdb 调试运行该core dump文件时,停在了strcasecmp函数内,bt和where都不能打印出正确的调用栈信息,栈信息被破坏,无法回溯。
形如:
xxxxxxxx strcasemcp () from /lib/libc.so.6
Backtrace stopped: Cannot access memory at address xxxxxxxx
将自定义strcasecmp函数编译成动态库,使用LD_PRELOAD加载该动态库,调用strcasecmp的地方将会调用自定义的strcasecmp函数。参考:Linux下LD_PRELOAD的简单用法 - 52coder
在strcasecmp内部输出参数信息,线程信息,或者调用栈信息(可保存到文件)。在正常情况下,的确能够输出参数信息和线程信息,调用栈信息输出的不正确(backtrace输出调用栈)。当发生异常时,不能运行到自定义strcasecmp函数内,直接异常,而且异常时的函数位置仍为libc.so.6中strcasecmp。自定义的strcasecmp未正确运行到。(估计是哪个地方没有设置正确)
core dump文件上显示了线程的名字,只有根据该线程逐步查找了,幸好可以比较容易复现。在线程各个位置上加入打印信息逐步查找,再根据自定义strcasecmp函数输出信息,直到找到未输出日志位置,锁定问题。