一次痛苦的Coredump定位过程
来源:互联网 发布:人人网络代理 编辑:程序博客网 时间:2024/05/16 15:11
http://blog.sina.com.cn/s/blog_4d6f62190100qlkw.html
大约从5月份开始,一台Server开始出现重启Worker Coredump的问题,期间负责该Server的两位同事先后就该问题进行了定位排查,由于该问题测试开发环境不可重现以及Coredump的堆栈信息基本乱掉,无有用线索可用,因此问题一直未得到解决。最近的一个月,发现每次发配置重启Server,必然有一堆WorkerCoredump,运维和开发同事都觉得该问题需要继续深挖定位。
因此专门安排任务让我跟进处理该问题。
该问题难以定位解决原因主要有以下几个方面:
1.
2.
3.
4.
下边简要说一下我处理该问题的整个过程(过程是痛苦的)
Step one:检查现网的Coredump文件
和其他两位同事一样,首先去现网查看coredump文件的信息,结果所获得的信息也一样,由于堆栈信息混乱,出错点不固定,总是在不同的代码上跳来跳去。
于是,在得不到任何有价值线索的情况下,走了以前同事走过的老路,压测以图在测试环境重现Coredump问题,最终无法重现。
Step two:review互动Coredump的代码
说实话,相关代码看了不下三遍,没有能够查处问题(其实问题就在业务逻辑代码中),这也证实了一句话,这种问题不一定能看出来。
Step three:按命令字server拆分
由于该Server本身包括了若干个接口,因此考虑在前端将Server按各个命令字分组,然后重启服务观察那组Server会出现Coredump,从而确定是由于那些命令字引起的Coredump,缩小排查定位范围。最终得到的结论是:其中的一个命令字导致服务重启时worker Coredump。
Step four:从Core文件堆栈信息混乱推测可能的coredump直接原因
由于Core文件堆栈信息混乱,因此推测可能是内存的越界些问题,写了自己不该写的内存,导致整个内存乱掉。在单独重启现网Server的时候,发现信息
======= Backtrace: =========
/lib/libc.so.6[0xf75e3cb1]
/lib/libc.so.6[0xf75e3dd0]
/lib/libc.so.6[0xf75e5a09]
/lib/libc.so.6(malloc+0x86)[0xf75e7596]
/usr/lib/libstdc++.so.6(_Znwj+0x27)[0xf7783807]
/usr/lib/libstdc++.so.6(_ZNSs4_Rep9_S_createEjjRKSaIcE+0x6b)[0xf775f13b]
/usr/lib/libstdc++.so.6(_ZNSs4_Rep8_M_cloneERKSaIcEj+0x38)[0xf775fcf8]
/usr/lib/libstdc++.so.6(_ZNSs7reserveEj+0x48)[0xf7760868]
/usr/lib/libstdc++.so.6(_ZNSt15basic_stringbufIcSt11char_traitsIcESaIcEE8overflow
/usr/lib/libstdc++.so.6(_ZNSt15basic_streambufIcSt11char_traitsIcEE6xsputnEPKci+0x81)[0xf775e321]
/usr/lib/libstdc++.so.6(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE13_M_insert_intImEES3_S3_RSt8ios_basecT_+0xf5)[0xf774c0b5]
/usr/lib/libstdc++.so.6(_ZNKSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE6do_putES3_RSt8ios_basecm+0x50)[0xf774c380]
/usr/lib/libstdc++.so.6(_ZNSolsEj+0xcd)[0xf7754d4d]
../lib/libinteractive.so(_ZN15CTopDishMapping6EncodeERSs+0x103)[0xf42eec41]
../lib/libinteractive.so(_ZN16InterActionSteal13Update
../lib/libinteractive.so(_ZN16InterActionSteal13API_StealFoodEjjRjRiRSs+0xbe1)[0xf42890a7]
../lib/libinteractive.so(_ZN15StealFoodAction6doImplER
../lib/libinteractive.so(_ZN14QUsrActionBase4doitEv+0x47)[0xf428b4c5]
../lib/libinteractive.so(_ZN13RubbishHander12rspStealF
../lib/libinteractive.so(_ZN13RubbishHander4doitEj
../lib/libinteractive.so(_ZN8SService18spp_handle_processEPcjRS0_Rj+0x7f8)[0xf4314bde]
../lib/libinteractive.so(spp_handle_process+0x5d)[0xf4315071]
./spp_interactive_worker(_ZN3spp6worker14CDefaultW
./spp_interactive_worker(_ZN5tbase6tcommu9tshmcomm
./spp_interactive_worker(_ZN3spp6worker14CDefaultW
./spp_interactive_worker(_ZN3spp4comm11CServerBase
./spp_interactive_worker(main+0x116)[0x80629da]
/lib/libc.so.6(__libc_start_main+0xdc)[0xf759587c]
./spp_interactive_worker(__gxx_personality_v0+0x95)[0x8062841]
从glibc打印出的信息和step three中的结论呼应,确实是其中的一个特定逻辑引起的core问题。而直接原因是由于内存分配链被损害了,导致分配内存coredump。
由于此处信息仍旧无法定位到具体的代码行上,因此就想到了不想进行的最终的处理措施,现网跑一valgrind,看看能否有发现。
Step five:现网跑valgrind
于是联系运维安装valgrind,准备跑程序查看。说明一点,在线网跑valgrind也是最终没有办法的办法,由于现网跑valgrind会降低worker 20-25倍的处理性能,因此必须要跑一次尽快退出,争取将对用户的影响降低到最低。结果在最终的valgrind日志中,发现了问题所在,
==15539==
==15539== Invalid write of size 4
==15539==
==15539==
==15539==
==15539==
==15539==
==15539==
问题的直接原因:
借用C++ Primer中的一句话:任何改变vector 长度的操作都会使已存在的迭代器失效。例如,在调用push_back 之后,就不能再信赖指向 vector 的迭代器的值了。
小结:引起coredump的问题代码,其实最终看起来是一处很小的问题,但就是这个问题引起的coredump却包含了极大的不确定,有时候core,有时候不core,core了又看不到有价值的线索。所以,core问题的定位还是要在发现之后,尽早定位(起码我们可以采用查看变更代码的方法确认一下)。C++给了程序员很大的权利,也带来了极大的风险,在使用指针、迭代器等元素的时候一定要注意内存问题。
PS:valgrind还是很强大的,赞一下!
- 一次痛苦的Coredump定位过程
- centos7 一次痛苦的安装过程
- 一次修改表为nologging状态的痛苦过程
- 一次Mac Pro操作系统(Mavericks)恢复的痛苦过程
- 一次BUG定位的过程与总结
- 一次定位“应用无法访问”的过程总结
- 一次奇怪的问题定位过程
- 痛苦的初学过程。。
- 痛苦的过程
- 记一次痛苦的过程-------源码编译安装apache+php5+mysql
- 利用coredump定位出错的代码行
- 一次痛苦的server调试经历
- 痛苦的一次rac 添加节点操作
- 记一次痛苦的编码问题处理
- 一次痛苦的Android应用死锁问题
- 阿里RDS一次数据异常的定位过程
- 记一次使用 git bisect 快速定位 bug 的过程
- 记录一次kernel内存泄漏的查找定位过程
- Android中AsyncTask的简单用法
- 该服务器的安全证书尚未生效
- C++ 毫秒时间
- java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
- 部分解决Source Insight中文输入法打开时输入的乱码问题和自动添加注释
- 一次痛苦的Coredump定位过程
- Android整体印象
- Total Commander配置详解
- Forms: How to Configure Forms Builder to run forms locally
- AS3.0 DisplayObjectContainer 属性和方法
- Using GNU C __attribute__
- C语言预定义宏__LINE__ __FILE__ __DATE__ __TIME__ __STDC__ __cplusplus
- Notify_sendEvent的实现过程
- ORACLE中meger的使用