当前位置: 华文星空 > 知识

有哪些让你目瞪口呆的 Bug ?

2020-03-11知识

这是一个历时5年,经过无数次排查才最终解决的BUG,而BUG的原因,却又简单到不可思议。

事情要追溯到2012年,我刚刚做程序猿不到1年,在公司做了一个网站程序,环境是小软件公司常见的Windows+C#+SQLServer微软组合,程序实现了什么功能不重要,某天突然有客户反映「登录不上去,一直提示验证码错误。」这个验证码我做的是随机取两个0-9的数拼个算式,之后生成图片让用户填答案(例如图片生成内容是1+1=?,客户要填2)。答案存在session里,用户提交的时候就把填写内容跟session里面的答案比对。在确定客户不可能一直做错这种最初级算术题的前提下,开始了DEBUG。

然而我没有想到的是,这个看似很小的BUG,却如影随形地跟随了我5年。

1、初次交锋

最初我在测试环境和正式环境下根据客户叙述分别试验,都未发现类似的BUG。尝试远程操作客户电脑,问题重现,排除了客户操作问题。尝试重新获取验证码、强制刷新、清除缓存等方法无效后。受到水平高超的网吧网管的最强解决方案(重启、换机器)启发,使用了【秘技:换个浏览器】,问题解决。

之后断断续续也有其他客户反映同样问题,也都通过此秘技恢复正常使用。但是这个奇怪的BUG原理却完全不明白。使用同样的功能,只有一部分用户会产生这个问题,其他大部分人都是正常的。

2、獠牙初现

好景不长,换浏览器大法使用后没多久,出现了第一批疑难杂症患者:问题又在新的浏览器上重现。

再继续换浏览器终究不是办法,通过各种手段也没排查到问题原因,甚至连公司的一个测试人员也遇到了这个BUG。之前更换其他内核浏览器就好用可能是因为缓存问题,但之前删除过缓存并没有起效。我们抱着玄学的态度,清除了浏览器缓存,然后刷新页面重新登录——登录成功。

原来IE这个功能其实清不干净。

于是我们的解决方案变成了【换成Chrome浏览器,如果还不行,就清缓存】

3、反击

通过各种排查,最终确定BUG来源于session丢失,因为.net的session机制是本地cookies存储了一个「ASP.NET_SessionId」,值与服务器上的sessionid对应,从而确定会话是来自哪台电脑。我当时猜测是因为本地cookies中的sessionid与服务器不对应,导致无法获取会话信息,所以session永远是空的。而清除了cookies之后,重新为客户端生成了新的sessionid,新的id有了对应后,问题解决。

因为在本地调试的用VS自带的IIS Express不会出现这个问题,所以我认为这是服务器上IIS的BUG,但是网上检索相关内容,无论是IIS的这个BUG,还是获取不到session都没有相关结果。

于是我心一横,决定自己写一套session,利用与iis类似的机制,通过客户端cookies中的一个id来与服务端对应,这样直接干掉了IIS的session,就可以不用为这个BUG烦恼了。

编写过程很顺利,新的session通过测试,正式使用。上线后经过几次细节修改,基本完美运行。

与session丢失BUG的战斗也告一段落————本该是这样的。

4、阴魂不散

树欲静而风不止,运行一段时间后,本应完全解决的BUG又卷土重来。与曾经一模一样的情况,所有需要用到session的地方,都是返回空值。与曾经一模一样的随机用户产生、难以复现。

反复排查,却一无所获,这个BUG最大的难点在于我们内部很难复现这个问题,所以十分难以调试,而出现了问题的客户,一般都没法连接到对方电脑操作。只能通过不断地猜测原因,然后修改代码,祈祷这次的改动是有效的,这次的猜测是正确的。

经过了数次修改,效果却并不理想。

5、柳暗花明

2017年的某天,正常工作中,在浏览器控制台中发现了一条异样的cookie信息

UserName=xxxx&Password=xxxx&copyright=xxxx

这条信息是我设置的自动登录,只要选择自动登录,便将账号和加密后的密码存储到cookies中:

HttpCookie cookie = new HttpCookie ( "AutoLogin" ); cookie . Expires = DateTime . Now . AddDays ( 14 ); cookie . Values . Add ( "UserName" , ul . UserName ); cookie . Values . Add ( "Password" , ul . Password ); cookie . Values . Add ( "copyright" , "公司名" ); Response . Cookies . Add ( cookie );

在控制台里面,copyright是乱码的,因为公司名字是中文,因为没报错所以就没关注过。进一步排查,终于发现了5年前那个BUG的产生原理:

cookies是以文本形式存储在硬盘里,而公司名字乱码恰巧吞掉了字符串结束的限定符,从而使得这个字符串无限延伸,吞掉了后面的cookies。从而在framework获取ASP.NET_SessionId的时候,取不到值,就产生了这个session黑洞。

至于为什么部分用户有这个问题,部分用户没有这个问题……因为大部分用户ASP.NET_SessionId这条是在AutoLogin前面,不会被吞掉,而在后面的,都被吞掉了。

最后删掉各项目中在cookies追加版权信息的代码后,问题解决,从此再也没出现过session黑洞。

最终,一个困扰了我5年的BUG,竟然是这种令人哭笑不得的原因,而耗费了不少心血编写和修改的自定义session组件,也因为经过几年的时间,在各个项目中已经有了非常广泛的应用,修改成本较高。再加上一直正常使用也没出什么问题,就继续用了下去。