第一次解BUG,有感

  刚工作,就给我安排解决BUG。刚解到第二个,就难了我很久————大概一个月。这是一个“奇怪”的BUG,至今还有很多疑问。

1.现象描述:基于C/S架构的一个远程设备管理系统。能在server端对client端开关机操作。但是有时(5次就会有)重启后client就挂了。

2.解决流程回顾:

  step1.按照现象重搭环境:client[centos 6.5] + server[windows 7]----------几十次重启无现象,与设备有关?

  step2.远端原BUG环境:client[centos 6.5] + server[windows 7]----------数次重启出现现象。 

  step3.dd出BUG镜像并dd到本地:数次重启出现现象,与系统有关?!

  step4.发现client端需要调用两个自己写的共享库[lib3,lib4],只要没有lib3就不会出问题。库使用c/C++写的,clint和server用C#;在 Linux上用mono制作成可脱离mono环境运行的可执行文件。

  step5.既然挂了无非程序退出或者被系统杀死(可能性大);由于是服务进程,开启core文件生成可得知情况,发现被11号信号杀死(段错误)。

  step6.可能是lib3的问题,获取源码加打印信息(函数首尾加打印信息到文件);结果该打印的地方都打印了。貌似在lib3返回到C#部分或者之后出问题了。放到自己做的centos6.5上试试,结果这个lib3的库压根没有运行[显示缺少系统库支持libx86-devel]。那么问题来了--之前在上面测试就没有走lib3;于是发现还有lib2,真是太糟糕了(也怪自己之前没有问问这个软件的依赖)!询问得知:

  目前的依赖关系:

          

  就是说两条通路都能达到目的。其中lib3的路有问题。然后我在自己做的centos6.5上去掉lib2通路,装上支持的运行库libx86-devel后。BUG现象100%出现。确实lib3有问题。但是打印信息显示lib3的函数都有正确执行!!

  难道是返回[return]时出问题了,这种情况就是破坏了堆栈信息。也就是破坏了返回地址,或着桟帧的栈底指针ebp。于是采用内嵌汇编的方式得到这两个值,在函数开始和返回前打印,内嵌汇编部分如下:  

 1 int addr = 0;
 2 int ebp = 0;
 3 __asm__ __volatile__( 
 4     "movl   4(%%ebp), %%eax  	
" 
 5     "movl   %%eax, %0        	
" 
 6     "movl   %%ebp, %%eax     	
"
 7     "movl   %%eax, %1        	
" 
 8     :"=r" (addr), "=r" (ebp)
 9     :
10     :"%eax");  

  结果是首尾打印的值相同!!没有这方面的问题。

  另外一个疑点是:为什么两个系统(BUG-os和自己做的os)表现不一样,bug-os不时发生;自己做的os却100%出现。

  step7.走投无路的情况下,在师傅指导下在挂之前的lib3库的那个函数中注释掉部分代码测试。结果发现了“罪魁祸首”——LRMI_init();[源于libx86.h]。发现只要存在它就会出现问题。看起来似乎是LRMI_init()与C#代码之间的问题?!因为挂的时候总是在C#部分。

  step8.写一个C#程序[使用mono-2.10.8进行脱离mono“包装”]加载一个只有LRMI_init()函数的共享库,执行发生段错误。进一步追查发现有LRMI_init()后导致mono中一个断言失效!所以发生了crash。具体怎么导致的还未追查清楚。

3.总结:

  1)存留两个问题:

    (1)为什么两个系统的现象存在差异?两个系统有什么不同?

    (2)具体导致断言失败的原因是什么?这个问题新版的mono还存在吗[后续验证]?

  2)学到的非技术经验:

    (1)相信自己合理的分析;我在这其中走了很多弯路,如果早点按自己的推断做去,可能会早点解决.

    (2)别人的建议很重要;像程序return崩溃的情况我以前没有听过,是别人告诉我的.

    (3)面对一个未知的软件,多从开发前辈那里获取信息会节省很多时间。  

        

原文地址:https://www.cnblogs.com/darling131499/p/4032316.html