捉BUG记(To Catch a Bug)
大约有一年整没有写一篇博客了,由于各种原(jia)因(ban)导致闲暇时间要么拿着IPad看岛国奇怪的片(dong)子(hua)、要么拿着kindle看各种各样的资(xiao)料(shuo)。本来想写的一个介绍MEF的专题也果断在完成50%后砍掉,结果这两天想准备点关于IOC(不是国际奥委会那个IOC)的内部材料,发现之前准备的一些资料也已经顺手删掉了,可惜可惜。
不说别的了,就说这两天自己给自己挖的一个坑。说起来还挺有趣的,原因不复杂,就是最基本的知识点,只是手头的模块略复杂,一开始还真没猜到自己是栽在这坑里。
一个BUG,一个关于IDisposable的故事
事情是这样的,前天下午同事屁颠屁颠跑过来,吼道:“报错啦,报错啦,天塌啦,地陷啦”,嗯,差不多他就是这个意思。
当然,他吼了什么一点都不重要,重要的是一番检查后确认是系统其他地方存在问题,这里抛出异常是合情的合理的合法的美帝大统领看到了也要喊YES WE CAN THROW独国默大妈瞧见了双手摊开轻身细语我要让世界知道这个异常是要抛的股神巴菲特听到了抛字一路比划着一路小跑而来请原谅我忘记了标点的用法因为标点已经阻碍了我表达对这个异常被抛出的正确性的认知。
通常来说,剧情发展到一半的时候,如果前期BOSS被干掉了,就意味着后面还要出现一个幕后黑手——要不然这戏份怎么凑啊编剧?这几年国产片各种捞票作,各种侮辱观众的智商的片子也没这么拍的嘛。
是的,同样的代码,同样的参数调用,第二次这异常就神奇的消失了……在确认天上没有Blink Blink小圆盘地下没有Pink Pink小圆神后,反复重试都是第一次抛异常,后面就默默的什么都没有了。由于代码层次较多,相关数据也很多,在代码战争的汪洋大海中一番折腾后总算找出了一番的BUG(差不多下面的意思):
class Foo : IDisposable
{
DbContext ctx;
...
public void Dispose()
{
ctx.SaveChanges(); //Fuck my life
... //其他资源释放
}
}
原先在设计Foo类的时候,希望调用者能在完成一系列的操作后整体保存修改到数据库中,如果报错则在新的Foo实例中重试(以防止EF的缓存导致数据污染)。由于EF将在SaveChanges时将内存中的修改放在一个事务中统一提交,也为了方便调用者使用此类,故而考虑了在Dispose()中调用SaveChanges()的做法。于是调用者可以采用如下轻松又愉悦的姿势调用:
using(var foo = new Foo())
{
...
}
到此,各位看官看出问题来了么?这个低级的错误刚看到时一时半会还真没想出来:
- using语句块相当于try...finally的简化写法,保证了实现IDisposable的资源在离开语句块时Dispose()方法会被执行。
- 由于处理过程中的异常没有被catch,故而异常被沿着调用堆栈逐级向上抛出——这不是重点,重点是程序离开了using语句块,所以Dispose()方法被!调!用!了!,Dispose()方法被!调!用!了!
- Dispose()方法被!调!用!了!因为很重要所以要说三遍,本条凑数用。
- 由于在异常抛出前,已经有部分实体的状态被修改,故而惨遭提交。Q.E.D.
还好本模块实现了事件溯源,高大上点的说法叫Event Sourcing。最终是发现在异常抛出后事件记录多了几条,才意识到这个坑爹的问题的。看来引入Event Sourcing的概念,虽然目前还没有发挥多少价值,就冲帮我找到了这个BUG上(如果直接查看数据,那真得疯掉了),值了。
发现问题,解决倒也简单。加个标记位简单记录下是否处理过程发生异常即可。正如张〇忌般,历经世事后迎来了回老家画眉(不愧是明教教主,就是躲过了回老家结婚的flag)的平淡结局。
标题NETA了希区柯克的《捉贼记》(To Catch a Thief),当然片子我还没看。
捉BUG记(To Catch a Bug)的更多相关文章
- 解Bug之路-串包Bug
解Bug之路-串包Bug 笔者很热衷于解决Bug,同时比较擅长(网络/协议)部分,所以经常被唤去解决一些网络IO方面的Bug.现在就挑一个案例出来,写出分析思路,以飨读者,希望读者在以后的工作中能够少 ...
- 捉虫记(四)线程安全导致的HighCpu
一个朋友QQ群里说网站启动后会cpu很高,想要帮忙看一下dump. 1.打开windbg加载dump文件后第一个命令lmf,这个命令显示加载的dll以及路径,这样子可以找个dll来帮忙加载sos,(额 ...
- ie7,8常见bug,共计257个bug汇总?如何解决ie的历史bug
ie7.8常见bug,共计257个bug汇总 针对web开发者来说,浏览器的bug,特备是ie的bug是很多人的噩梦,因为ie的更新换代没有ff,chrome,safari,opera那么快,而且ie ...
- 软件测试中Bug的生命周期以及Bug的严重等级
软件测试中Bug的生命周期以及Bug的严重等级 我猜你们都会,但能说专业且全面不? 1.首先当测试人员接到一个项目或产品准备测试的时候,测试人员会根据测试用例一步步的来执行用例进行简单的功能测试.当测 ...
- DK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。
NIO的epoll空轮询bug - Lost blog - 博客园 https://www.cnblogs.com/JAYIT/p/8241634.html NIO的epoll空轮询bug JDK ...
- 软件测试过程中如何区分什么是功能bug,什么是需求bug,什么是设计bug?
问题描述: 测试过程中如何区分什么是功能bug,什么是需求bug,什么是设计bug? 精彩答案: 会员 土土的豆豆: 本期问题其实主要是针对不同方面或纬度上对于bug的一个归类和定位. 个人认为,从软 ...
- 记一次偶发的bug排查——redis-py-cluster库的bug
排查流水账: 通过平台监控,发现很多偶发的查看推荐列表的接口时延大于0.5s 写单元测试,不能重现.在测试环境不能重现.只有在正式环境可以偶发重现. 通过日志埋点,等待重现 不断地加日志埋点后发现耗 ...
- 记一次令人发狂的 bug Eclipse 开不开 tomcat 7.0
改项目,结果发现以前的项目也出了问题,就删除了系统用户下面workplace里的文件夹,结果,eclipse被清空,重新添加项目,发现一堆bug; 最让我崩溃的是,用tomcat 7.0跑项目,反复出 ...
- 记一个神奇的Bug
多年以后,当Abraham凝视着一行行新时代的代码在屏幕上川流不息的时候,他会想起2019年4月17日那个不平凡夜晚,以及在那个夜晚他发现的那个不可思议的Bug. 虽然像无数个普普通通的夜晚一样,我在 ...
随机推荐
- IDE神器intellij idea的基本使用
摘自: http://www.cnblogs.com/newpanderking/p/4887981.html 一.编码快捷键(比较常用的快捷键)该套快捷键选择的是:Mac OS X 10.5+ 1. ...
- 碎片事物的提交 commitAllowingStateLoss()
转:http://blog.csdn.net/kaiqiangzhang001/article/details/42241441 下边两个问题,是在开发中碰到的一些关于Fragment的偶发性的问题, ...
- Oracle 查询类似 select top 的用法
--查询前10条数据select * from MID_EHR_STAFF where rownum<10;--查询第5~10条的记录,minus(减)select * from MID_EHR ...
- Asp.Net 获取FileUpload控件的文件路径、文件名、扩展名
string fileNameNo = Path.GetFileName(FileUploadImg.PostedFile.FileName); //获取文件名和扩展名string Directory ...
- eclipse颜色 字体
字体 之前也想过搜个字体,但是看了别人的推荐也没什么太大感觉.今天我自己选择了一款字体,发现看着单词中的i等瘦型的字母会比较费力,现在我知道自己想要什么样的字体了.网上推荐Inconsolata.pf ...
- Linux(centos)系统各个目录的作用详解
Linux(centos)系统各个目录的作用详解 文件系统的类型 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码 ...
- 【POJ2949】Word Rings(最大平均值环)
题意:给定N个字符串,如果A串的最后两个字母跟B串的前两个字母相同它们就能连接. 求一个由字符串组成的首尾相连的环,使(字符串总长度/字符串个数)最大. n<=100000 len<=10 ...
- 安卓手机开机开启指定Activity
1.布局 默认helloworld布局 2.class BootCompleteReceiver package lpc.com.project522; import android.content. ...
- Java关键字总结及详解
Java关键字是Java的保留字,这些保留字不能用来作为常量.变量.类名.方法名及其他一切标识符的名称. 一.基本数据类型 Java中有八种基本数据类型,六种数字类型(四个整数型.六中浮点型),一种字 ...
- node.js 基础学习笔记2
Module和Package是Node.js最重要的支柱. Node.j 提供require函数来调用其他模块,而且模块都是基于文件.模块和包区别是透明的,因此常常不作区分. 1.模块和文件一一对应. ...