捉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. 虽然像无数个普普通通的夜晚一样,我在 ...
随机推荐
- mysql 不是主键不能删除的保护问题解决办法?
select * from t_answerexams; delete from t_answerexams where selectid = 'c4582502-8b27-44 ...
- threadlocal类
1.threadlocal对象为线程提供变量的副本,该副本为线程私有的,其它线程访问不到: 2.变量的副本存储在ThreadLocalMap对象中: 3.使用threadlocal时候,最好先使用in ...
- 第十六章 综合实例——《跟我学Shiro》
简单的实体关系图 简单数据字典 用户(sys_user) 名称 类型 长度 描述 id bigint 编号 主键 username varchar 100 用户名 password varchar 1 ...
- MAXIMO-IBM文件夹的笔记
MAXIMO--IBM整套文件的目录结构及常用的文件说明: applications文件装的maximo的最重要的文件,包括ear包等发布文件. 进入applications文件夹里,maximo文件 ...
- windows下gethostbyname 调用失败
gethostbyname()函数属于WinSock API库,而在使用WinSock API之前,必须调用WSAStartup函数,只有该函数成功返回(表示应用程序与WinSock库成功地建立起连接 ...
- Python 前端之JS
JavaScript由浏览器编译运行 JS的导入方式有两种,一种直接定义,第二种通过src引入:可以存放在<head>头部,但是强烈建议放在<body>的最下面,因为如果你引入 ...
- CodeForces 689C Mike and Chocolate Thieves (二分)
原题: Description Bad news came to Mike's village, some thieves stole a bunch of chocolates from the l ...
- 《深入理解Nginx》阅读与实践(三):使用upstream和subrequest访问第三方服务
本文是对陶辉<深入理解Nginx>第5章内容的梳理以及实现,代码和注释基本出自此书. 一.upstream:以向nginx服务器的请求转化为向google服务器的搜索请求为例 (一)模块框 ...
- 程序的删除kill、killall
发送信号给程序,或者列出信号集 SYNOPSIS kill [-s SIGNAL | -SIGNAL] PID... kill -l [SIGNAL]... 1.信号操 ...
- Ubuntu-12.04-server 配置修改静态 IP地址
前几天在装Ubuntu 12.04 Server版系统的服务器时IP地址写错了,导致服务器不能上网,今天重新修改了一下IP地址,这里做一个总结. 1.配置静态IP地址 sudo vi /etc/net ...