修改一行代码的顺序引发恶心bug

来源:互联网 发布:数据库基础视频 编辑:程序博客网 时间:2024/05/17 06:45

起因

原来的代码

    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

      

原创粉丝点击