The hardest bug i've debugged

事出有因

全部都是看这个帖子有感What’s the hardest bug you’ve debugged?

先说文章本身——只有四个字——不明觉利,我的感觉是这样,连作者自己也是这种感觉。(我就不吐槽最后那个渣总结了,什么“用到了量子力学debug”,真心不知道怎么得出这个结论的)

然后发现程序员真心是一类奇怪的生物,什么东西都能拿来炫耀:最难的bug、最奇葩的注释、最难懂的代码etc,简直就是“伤疤是男人勋章”心理的升级版。

说回主题,这两年来我遇到的最厉害的bug——因为海森堡测不准原理哥德巴赫猜想引起的网卡罢工。

天降谜团

流水账模式switched√

某次版本发布,第一天风平浪静。第二天站点突然就挂掉了,而且直接是挂到ping不通了。嗯,机器出问题了,一定是这样,用另一块网卡远程reboot了机器,站点又跑起来了。过了一段时间,又挂了。突然就蒙了——我用的是asp.net,离网卡还有两层远呢,再怎么在clr上写代码,也不能把操作系统写到crash吧。还是坚信是操作系统自己的问题,跟我的代码无关。

然后,运营人员把代码回滚了,整整两天没crash过了。

这下真是三观尽毁了。

扑朔迷离

开始认真的分析问题:1.从代码层面入手,找两个版本的diff 2.从log入手,不放过一切蛛丝马迹。

第一条路不太好走,因为两个版本之间的diff真心有点太多了,而且从心理和经验上,我都不认可有代码可以把系统搞crash(心理上接受不了的东西是不会有动力做下去的)。那就只好从第二条路入手了,把所有log搞到,柯南模式开启!不过在biang的一声想到凶手之前,柯南还是遇到了许多挑战的:我主要是想从iis log入手,找机器挂掉的时间附近的访问记录,希望能找到引发故障的源头。但是——人生最厉害的就是这个但是了——iis一天的日志有点太大了,直接用notepad之类的肯定是打不开,想用ruby写个程序直接分析出结果,但是机器内存还没文本的大小大……好吧,又准备写个程序一点一点读,把文本切成几节来处理。

等等,这是不是有点太麻烦了,难道没人遇到过类似的问题么?

果然google了一下——救星出现——logparser(GUI版本叫lizard,我们这些windows的小白最喜欢用鼠标低端的点点点了)用起来,不仅日志大小通吃,还能直接用类sql的语言查询。太开心了,几下就找到了出问题的时间点(怎么找?这个问题很简单,如果你看过iis的日志就知道,iis每次重启以后的第一条日志前面都会插入一段类似注释的东西)。发现每次当机之前有一系列频度很高的访问,那个接口相当简单,就是在做简单的keep-session-alive的工作罢了,访问频率大概是每秒一次(用户打开某个页面的时候会一直访问)。这就能让windows crash?太假了,随便放到几台测试的机器(有实体有虚拟机)上试了一下,打开N多页面跑一上午也没问题。

真相大白

没想到,程序员最爱用的借口之一——环境问题——竟然成真了!这里还有个特别奇怪&重要的现象就是:在生产环境的机器上竟然在eventviewer里找不到系统crash的日志,不要说dump,连个error都没有。这个问题明显不是我能解决的了,老大帮忙联系了微软的顾问(不得不帮ms软文一句:付钱的服务就是不一样,各种周到,并且相当专业),帮着采了一大堆数据,开始在各种工程师的指导下dump、上传、分析。然后顾问也跟我得出了基本类似的结论——服务器的网卡会在某些特定的情况下直接罢工,那时OS(当然包括iis、.NET)还是在正常工作的。

最后还是来到了biang一声破案的时刻,屁颠屁颠的跑到了机房,给机器接上了显示器,远程开始访问那个页面,等了15分钟之后,网卡直接在设备管理器中变成黄色感叹号了,ping任何其他机器都没了反映。然后,微软的顾问相当礼貌和专业的表示可以帮我联系服务器的厂商帮忙做硬件的debug,虽然我还挺想,但是好像没那个必要了(现在向来有点遗憾没能玩一下网卡的debug),事件终了。

感想:

  1. 工具很重要,善用工具解决很多问题
  2. 敢打敢拼(好久没听张老师解说了),虽然环境问题之类的多数时候是借口,但另一些时候是真相
  3. 只要是bug都能debug