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

创建线程后调用BOOST_LOG_SEV导致async_read_some异常的问题咨询

解决Boost.Asio串口异步读取加日志后的异常问题

这问题我之前帮同事排查过几乎一模一样的情况,大概率是线程生命周期或者日志线程安全的锅,咱们一步步拆解:

最可能的原因:IO服务线程提前退出

你现在的代码顺序是先启动io_service的线程,再发起async_read_some异步操作——这里有个极易踩的坑:如果io_service.run()调用时没有待处理的异步任务,它会立刻返回,线程直接结束。

为什么加日志后才出问题?因为日志输出需要消耗少量时间,让IO线程有足够的时间完全退出,等你调用async_read_some时,已经没有线程在处理IO服务的任务了,自然会表现出“异常”(比如回调永远不触发、操作超时)。

对应解决方案

有两种靠谱的处理方式:

  1. 调整顺序:先发起异步操作,再启动IO线程
    先调用port_->async_read_some(...)把任务塞进IO服务,再启动线程执行io_service.run(),这样线程启动后就有任务可处理,不会直接退出。
  2. 用io_service::work保持线程存活
    创建一个work对象绑定到你的IO服务上,只要这个对象存在,io_service.run()就会一直阻塞(即使没有任务),直到你主动停止IO服务或者销毁work对象:
    // 在启动线程前创建work对象(注意生命周期要覆盖IO线程的运行时间)
    boost::asio::io_service::work keep_alive(io_service_);
    boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service_));
    

第二个可能:Boost.Log的线程安全或初始化问题

Boost.Log内部依赖线程本地存储(TLS),如果初始化时机不对或者sink没有配置线程安全,跨线程的日志操作可能会干扰IO服务的正常运行:

  • 确保全局日志初始化在所有线程启动前完成:比如在main函数最开始就初始化日志核心、sink和日志器,不要等到线程启动后才初始化。
  • 配置日志sink为线程安全:如果用了文件或自定义sink,需要明确开启线程安全选项。比如文件sink的配置:
    auto file_backend = boost::log::sinks::text_file_backend::create();
    file_backend->set_file_name_pattern("serial_log_%Y%m%d.log");
    // 开启线程安全模式
    file_backend->set_thread_safe(true);
    auto file_sink = boost::log::sinks::synchronous_sink<decltype(file_backend)>::create(file_backend);
    boost::log::core::get()->add_sink(file_sink);
    
  • 检查日志器获取的线程安全性:MBLog::get()返回的日志器实例要确保是线程安全的,不会在多线程环境下返回无效指针或未初始化的对象。

其他排查方向

  • 检查缓冲区生命周期:确保read_buf_raw_在async_read_some的回调函数执行完成前一直处于有效状态——异步操作会持有缓冲区的引用,如果缓冲区提前销毁,会触发未定义行为(崩溃、数据乱码等)。
  • 调试IO线程状态:给IO线程加个收尾日志,看看它是否真的提前退出了:
    boost::thread t([&](){
        std::size_t processed_tasks = io_service_.run();
        BOOST_LOG_SEV(MBLog::get(), boost::log::trivial::info) 
            << "IO服务线程退出,共处理了" << processed_tasks << "个任务";
    });
    
    如果输出的processed_tasks是0,就说明线程启动时没有任务,直接退出了,这就坐实了第一个原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:14:00