• boost::asio::ip::tcp::acceptor::async_accept 一直被死循环调用(无错误)问题的处理。


    演示会发生异步死循环故障的代码实现:

    1. bool Socket::AcceptLoopbackAsync(
    2. const Hosting& hosting,
    3. const boost::asio::ip::tcp::acceptor& acceptor,
    4. const BOOST_ASIO_MOVE_ARG(AcceptLoopbackCallback) callback) noexcept {
    5. if (!acceptor.is_open()) {
    6. return false;
    7. }
    8. if (!hosting || !callback) {
    9. Closesocket(acceptor);
    10. return false;
    11. }
    12. const AsioContext context_ = hosting->GetContext();
    13. if (!context_) {
    14. Closesocket(acceptor);
    15. return false;
    16. }
    17. boost::asio::ip::tcp::acceptor* const acceptor_ = addressof(acceptor);
    18. const Hosting hosting_ = hosting;
    19. const AcceptLoopbackCallback accept_ = BOOST_ASIO_MOVE_CAST(AcceptLoopbackCallback)(constantof(callback));
    20. const AsioTcpSocket socket_ = make_shared_object(*context_);
    21. acceptor_->async_accept(*socket_,
    22. [hosting_, context_, acceptor_, accept_, socket_](const boost::system::error_code& ec) noexcept {
    23. if (ec == boost::system::errc::operation_canceled) {
    24. Closesocket(*acceptor_);
    25. return;
    26. }
    27. bool success = false;
    28. do { /* boost::system::errc::connection_aborted */
    29. if (ec) { /* ECONNABORTED */
    30. break;
    31. }
    32. int handle_ = socket_->native_handle();
    33. Socket::AdjustDefaultSocketOptional(handle_, false);
    34. Socket::SetTypeOfService(handle_);
    35. Socket::SetSignalPipeline(handle_, false);
    36. Socket::SetDontFragment(handle_, false);
    37. Socket::ReuseSocketAddress(handle_, true);
    38. /* Accept Socket?? */
    39. success = accept_(context_, socket_);
    40. } while (0);
    41. if (!success) {
    42. Closesocket(socket_);
    43. }
    44. success = AcceptLoopbackAsync(hosting_, *acceptor_, forward0f(accept_));
    45. if (!success) {
    46. Closesocket(*acceptor_);
    47. }
    48. });
    49. return true;
    50. }

    该问题发生的原因:

    进程的最大文件描述符太小,当进程打开的文件描述符句柄(fd)数量超过,当前进程的 “Max open files”,那么会导致 accept 无法获取 session fd 而失败,但它并不产生错误,而此时 TCP/IP 连接的三次握手(或 FAST OPEN,单次)已建立连接。

    boost::asio 采用 epoll LT(水平出发模式),该模式会导致,epoll 不停的触发 accept 事件到达,所以就产生了无限制的 async_accept 回调调用,故而又重新 async_accept,造成的死循环,即使没有实际的网络IO产生。

    查看特定进程的 “Max open files” 值大小,人们可以使用以下的命令

    cat /proc/进程PID/limits                        ## 打印内容如下

    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             1178                 1178                 processes 
    Max open files            1000000              1000000              files     
    Max locked memory         67108864             67108864             bytes     
    Max address space         unlimited            unlimited            bytes     
    Max file locks            unlimited            unlimited            locks     
    Max pending signals       1178                 1178                 signals   
    Max msgqueue size         819200               819200               bytes     
    Max nice priority         0                    0                    
    Max realtime priority     0                    0                    
    Max realtime timeout      unlimited            unlimited            us

    通过命令设置当前终端会话,最大文件描述符数量:

    ulimit -n 1000000               ## 默认数量:1024

    确定某个进程打开的文件描述符数量

    lsof -Pnl +M -p 进程ID | wc -l 

    确定某个进程打开的文件描述符详细信息

    lsof -Pnl +M -p 进程ID

  • 相关阅读:
    Delphi版设计模式
    Linux音频系统编程之芯片平台适配功放Codec Driver解读
    精仿微信UI应用,基于SumerUI 3.0和Uniapp前端框架的一款仿微信APP应用,界面漂亮颜值高,视频商城小工具等,朋友圈视频号即时聊天 用于视频,商城,直播,聊天,等等场景,源码分享
    AUTOSAR从入门到精通-基于 CAN 总线的汽车发电机智能调节器
    【Unity3D】游戏物体操作 ④ ( 选中多个游戏物体操作 | 复制选中物体 | 聚焦选中物体 | 激活、禁用选中物体 | 对齐选中物体 )
    WSN final fighting 12.05
    es和kibana单机搭建
    java基于springboot+vue的人才推荐求职招聘系统
    Linux实验一(常见命令与场景) 基本命令&&权限管理
    【机器学习】Tensorflow.js:我在浏览器中使用机器学习实现了图像分类
  • 原文地址:https://blog.csdn.net/liulilittle/article/details/126773845