BOOST::ASIO多线程下socket关闭导致进程崩溃问题定位及解决

背景:

        本系统为我公司开发的一套商用车车联网系统的网关子系统,采用C++基于BOOST库开发,网络开发库采用了BOOST的ASIO库,线程池采用了基于BOOST的ThreadPool库。

        本次问题中涉及两个线程在不同时刻对同一个SOCKET的操作,这两个线程分属不同的类。

现象:

    系统接入实车进行测试后,在某些场景开会在read时发生异常,或直接抛出错误,或连续多次读到长度为0的数据包(甚至进入死循环),这时候,程序会关闭SOCKET连接,但是若在此时,另一线程正好正在对此SOCKET进行写操作,则会导致系统崩溃

定位:

      core dump 文件:

      #1  0x0000000000451b64 in MessageSender::send(HDConstants::TaskDef*, int) ()
      #2  0x0000000000473a0a in ThreadPoolGateway::abort(HDConstants::TaskDef*, SQ::Memory**, bool, int) ()
      #3  0x0000000000470cc3 in ThreadPoolGateway::task(HDConstants::TaskDef*) ()
      #4  0x0000000000442e2e in boost::function0<void>::operator()() const ()
      #5  0x0000000000444aa3 in        

      boost::threadpool::detail::worker_thread<boost::threadpool::detail::pool_core<boost::function0<void>,             boost::threadpool::fifo_scheduler, boost::threadpool::static_size, boost::threadpool::resize_controller, boost::threadpool::wait_for_all_tasks> >::run() ()
      #6  0x00007f41b0ded1d0 in thread_proxy () from ./lib/libboost_thread.so.1.60.0
      #7  0x000000322a2079d1 in start_thread () from /lib64/libpthread.so.0
      #8  0x0000003229ee8b6d in clone () from /lib64/libc.so.6

     日志文件:

      2016-09-05 15:12:13.432408 [0x00004410-0x00007f4584405700] [1]: LocalTCPConnection::handleRead received msg length:0 ipaddr = 117.136.98.68 port = 10189

     2016-09-05 15:12:13.432499 [0x00004410-0x00007f45906d5700] [0]: MessageSender::send enter
     2016-09-05 15:12:13.432505 [0x00004410-0x00007f4584405700] [1]: ipaddr= 117.136.98.68 port= 10189 tcp connection closed. error: End of file

     2016-09-05 15:12:13.432525 [0x00004410-0x00007f45906d5700] [1]: MessageSender::send response msg:7e8001000501150204111601ff01ff000200937e

     从COREDUMP文件中看,系统崩溃前正在执行send操作,结合日志,发现此时另一线程发现读到了长度为0的数据包,进而执行了断开TCP的操作,而此时SEND操作还未被执行完,从而导致系统崩溃。

解决方案:

     查询代码,其断开TCP的处理代码如下:

     if(e || bytesTransferred == 0){
        status = CONNECTIONCLOSED;
        boost::system::error_code ec;
        socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
        try
        {
            LOG_DEBUG<<"ipaddr= "<<addr4<<" port= "<<port<<" tcp connection closed. error: "<<e.message()<<endl;
            socket.close();
        }
        catch(boost::system::error_code& ex)
        {
            LOG_DEBUG<<"ipaddr= "<<addr4<<" port= "<<port<<"catch exception ex:"<<ex.message()<<endl;
        }
        return;
    }

    此处理比较简单直接,直接关闭了TCP的读写操作,然后释放了TCP连接的资源。

     

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值