您的位置:首页 > 编程语言

修改一行代码的顺序引发恶心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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐