修改一行代码的顺序引发恶心bug
2012-10-24 18:18
337 查看
起因
原来的代码
m_recvBuffer->Clear();
m_multiplexor->Register(this, Herm::READ_MASK);
Session初始化的时候,先把接收buffer清空,再注册读事件。
几周前,加了一个小功能, 抽了一个小函数,最后代码顺序变化了一下
m_multiplexor->Register(this, Herm::READ_MASK);
m_recvBuffer->Clear();
悲剧出现了,在大量的客户端连接,发请求数据的时候,有很低的概率出现某个客户端没收到回应。
这个东西是前几年整理的,这几年基本没怎么动了,细节流程没有完全存在脑子里,一开始根本没有想到是几周改的出现问题。
首先怀疑是应用层的对象是不是越界把地下的通信Session给写坏了。比较棘手的是,用测试程序也不容易重现这个bug,正常调试一点问题都没有。
花了好几个小时,各种可能一一排除了,最后根据一个现象,刚开始的时候m_recvBuffer有数据,但后面的时候,内部数据读写位置(这个buffer是环形队列)直接全变成0了。
上层直接把这个buffer给清掉了?把应用逻辑全去掉,用测试工具测,还是会出现。说明问题还是在底层代码本身。 后来怀疑到m_recvBuffer->Clear()头上,这个东西是把
buffer内部的读写位置全清0的。
bug分析
主线程
连接过来的时候,主线程先创建一个 socket handle,调用上面两行代码,清空buffer,同时注册读事件到epoll。
通信线程
当主线程注册读事件的时候,socket buffer有数据会马上得到通知,立刻把数据直接收到m_recvBuffer。
main thread Register Read
net thread Receive(m_recvBuffer, ....);
main thread m_recvBuffer->Clear(); // 这个时候刚收到的数据就没有了。
m_recvBuffer->Clear()放在m_multiplexor->Register(this, Herm::READ_MASK);前面,这个Bug基本可以避免(其实没有Memory Barrier情况下,处理器并不能保证Clear()一定在Register()前面, 但从实际情况看,这个概率事件可以不考虑了)。
blog.csdn.net/herm_lib
原来的代码
m_recvBuffer->Clear();
m_multiplexor->Register(this, Herm::READ_MASK);
Session初始化的时候,先把接收buffer清空,再注册读事件。
几周前,加了一个小功能, 抽了一个小函数,最后代码顺序变化了一下
m_multiplexor->Register(this, Herm::READ_MASK);
m_recvBuffer->Clear();
悲剧出现了,在大量的客户端连接,发请求数据的时候,有很低的概率出现某个客户端没收到回应。
这个东西是前几年整理的,这几年基本没怎么动了,细节流程没有完全存在脑子里,一开始根本没有想到是几周改的出现问题。
首先怀疑是应用层的对象是不是越界把地下的通信Session给写坏了。比较棘手的是,用测试程序也不容易重现这个bug,正常调试一点问题都没有。
花了好几个小时,各种可能一一排除了,最后根据一个现象,刚开始的时候m_recvBuffer有数据,但后面的时候,内部数据读写位置(这个buffer是环形队列)直接全变成0了。
上层直接把这个buffer给清掉了?把应用逻辑全去掉,用测试工具测,还是会出现。说明问题还是在底层代码本身。 后来怀疑到m_recvBuffer->Clear()头上,这个东西是把
buffer内部的读写位置全清0的。
bug分析
主线程
连接过来的时候,主线程先创建一个 socket handle,调用上面两行代码,清空buffer,同时注册读事件到epoll。
通信线程
当主线程注册读事件的时候,socket buffer有数据会马上得到通知,立刻把数据直接收到m_recvBuffer。
main thread Register Read
net thread Receive(m_recvBuffer, ....);
main thread m_recvBuffer->Clear(); // 这个时候刚收到的数据就没有了。
m_recvBuffer->Clear()放在m_multiplexor->Register(this, Herm::READ_MASK);前面,这个Bug基本可以避免(其实没有Memory Barrier情况下,处理器并不能保证Clear()一定在Register()前面, 但从实际情况看,这个概率事件可以不考虑了)。
blog.csdn.net/herm_lib
相关文章推荐
- 修改一行代码的顺序引发恶心bug
- 修改一行代码,解决在C++ Builder平台上JSONCPP向数组添加元素的Bug
- 修改一行SQL代码 性能提升了100倍
- 逻辑复杂的业务代码如何实现有顺序的跳转展示(登录成功后要去摇奖,设置预留信息,修改密码,弹窗警告......等等)
- Git 修复 bug 切换分支时,如何保存修改过的代码(即如何保存现场)?
- 如何修改一次代码就可以完成多种类型 cell 的 UITableView 增删修改顺序?
- 一行代码绕过原密码,直接修改win系统密码,bat命令,超神奇
- 公用表表达式(CTE)引发的改变执行顺序同WHERE条件顺序引发的bug
- 修改一行SQL代码 性能提升了100倍
- C#中DataGridView绑定了DataTable后,通过代码修改DataGridView中的数据,总有一行(被修改过并被用户选中的行集合中索引为0的行)不能被UpDate回数据库的问题和解决办法
- 优化代码,引发了早期缺陷导致新bug
- git小技巧:git blame && git show 查看某一行代码的修改历史
- 通过比对版本和代码修改历史定位由于代码修改引发的新问题
- 程序员的恶性循环:加班->没空学习->老是写同等水平代码->无法提升代码质量->老是出BUG->老是需要修改->加班->...
- 使用jfinal-routebind出现bug导致修改代码后jetty无法正常重启
- 一行代码轻松修改 Text Field 和 Text View 的光标颜色 — By 昉
- 编写安全代码:避免奇怪的逻辑引发的bug
- Android:用代码修改一行文字中某几个字的颜色
- [WCF]缺少一行代码引发的血案
- [难忘的找BUG]一行代码花去我两天时间