You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

boost::beast::websocket关闭后io_context::run()仍阻塞的排查与解决

问题场景与解决:Boost.Asio线程池配合WebSocket流的阻塞问题

场景说明

  • 使用线程池并发调用同一个io_context运行2个WebSocket流,需执行async_read、async_write等IO操作
  • 每个WebSocket流使用独立strand,通过额外锁保证async_read/async_write不会在前置操作完成前执行

原核心代码

io_context context;
std::vector<std::thread> pool(std::thread::hardware_concurrency());
...
wss(make_strand(context),ssl);
...
wss.async_read(&loop_read_handler);
...
for(auto& th:pool)
    th=std::thread([&]{
        try{
            start_read_loop();//give work to do to each thread
            context.run();
        }catch(...){}
        wss.close(...);//closing the websocket stream, expected to cancel all threads
        context.stop();//with or without it, no change
    });
for(auto& th:pool)
    th.join();//hangs here since the other threads did not return from run()

问题现象

调用close(boost::beast::websocket::close_code::normal, ec)关闭流时:

  • 当前线程的IO操作会被取消(收到带boost::beast::websocket::error::closed错误码的空消息)
  • 其他线程挂起,context.run()未检测到流关闭仍等待消息
  • 单线程池时无此问题,无论从IO操作内外调用close或context.stop()都无法解决阻塞

修改后代码

io_context context;
auto work=make_work_guard(context);//<<<<<<<<<<<<<<<<<<<
std::vector<std::thread> pool(std::thread::hardware_concurrency());
...
wss(make_strand(context),ssl);//I keep it because I will add other streams
...
for(auto& th:pool)
    th=std::thread([&]{
        try{ context.run(); }catch(...){} //<<<<<<<<<<<<<<<<<<<<<<<<<
        close_wss_streams_once_each(...);//cancels all threads
    });
start_async_read_loop();//<<<<<<<<<<<<<<<<<<<
work.reset();//<<<<<<<<<<<<<<<<<<<<<<<<<
for(auto& th:pool)
    th.join();

原因分析

  • 原代码错误地在每个线程中提交IO操作,导致线程池任务调度异常
  • 使用work_guard可以在IO任务未全部提交完成前,阻止io_context.run()因无待处理任务提前返回
  • 统一在线程池初始化完成后启动一次读循环,避免重复提交任务引发的线程阻塞

内容的提问来源于stack exchange,提问作者kmft3kte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:40:17