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

Boost ASIO多线程应用跨线程投递任务时崩溃问题排查

问题分析与解决方案

方案可行性说明

每个线程独立使用io_context的方案完全可行,这是Boost ASIO官方推荐的高扩展性模型(即"per-thread io_context"模式),跨线程通过asio::post投递任务本身是线程安全的,不需要额外加锁。你的崩溃问题并非方案本身的问题,而是代码中生命周期管理和异步逻辑的错误导致的。

崩溃原因分析

  1. 无限循环的异步等待导致io_context无法正常退出:原代码中handler会无限调用async_wait,即使reset work guard,io_context也会因持续有pending任务而无法退出,程序会一直阻塞在join()。若强制终止程序,会引发对象销毁时的竞争,导致段错误。
  2. 局部变量引用的生命周期风险:handler捕获了main函数中局部变量的引用,虽然正常流程中引用有效,但一旦程序出现异常或提前退出,会导致悬空引用,触发未定义行为。
  3. 阻塞调用违反异步编程模型:usleep是阻塞调用,会占用io_context线程,导致无法及时处理其他任务,可能引发调度器内部的异常。

修复后的代码示例

#include <boost/asio.hpp>
#include <iostream>
#include <iomanip>
#include <memory>
#include <atomic>
#include <thread>

namespace asio = boost::asio;
using namespace std::chrono_literals;
using boost::system::error_code;

static std::atomic_int tid_gen = 0;
thread_local int const tid     = [] { return ++tid_gen; }();
static constexpr auto  now = std::chrono::steady_clock::now;
static auto const      start   = now();
static std::mutex console_mx;

void trace(auto const&... msg) {
    std::lock_guard lk(console_mx);
    std::cerr << "at " << std::setw(8) << (now() - start)/1ms << "ms - tid:" << tid << " ";
    (std::cerr << ... << msg) << std::endl;
}

void worker(asio::io_context& ioContext) {
    trace("Worker thread enter");
    ioContext.run();
    trace("Worker thread exit");
}

int main() {
    try {
        asio::io_context ioContext1;
        asio::io_context ioContext2;

        // 使用shared_ptr管理定时器,确保生命周期覆盖异步操作
        auto task1 = std::make_shared<asio::steady_timer>(ioContext1, 100ms);
        auto task2 = std::make_shared<asio::steady_timer>(ioContext2, 200ms);

        // 原子变量控制程序退出
        std::atomic_bool running = true;

        // 任务1的handler,捕获shared_ptr避免悬空引用
        std::function<void(const error_code&)> handler1;
        handler1 = [task1, &handler1, &ioContext2, &running](error_code ec) {
            if (!ec && running) {
                // 用异步延迟替代usleep,避免阻塞io_context线程
                asio::steady_timer delay(task1->get_executor(), 5ms);
                delay.async_wait([task1, handler1, &ioContext2, &running](error_code delay_ec) {
                    if (!delay_ec && running) {
                        asio::post(ioContext2, []{
                            trace("Task1 posted job on Task2");
                        });
                        task1->expires_after(100ms);
                        task1->async_wait(handler1);
                    }
                });
            }
        };
        task1->async_wait(handler1);

        // 任务2的handler,同理使用shared_ptr管理生命周期
        std::function<void(const error_code&)> handler2;
        handler2 = [task2, &handler2, &ioContext1, &running](error_code ec) {
            if (!ec && running) {
                asio::steady_timer delay(task2->get_executor(), 10ms);
                delay.async_wait([task2, handler2, &ioContext1, &running](error_code delay_ec) {
                    if (!delay_ec && running) {
                        asio::post(ioContext1, []{
                            trace("Task2 posted job on Task1");
                        });
                        task2->expires_after(200ms);
                        task2->async_wait(handler2);
                    }
                });
            }
        };
        task2->async_wait(handler2);

        // 创建work guard防止io_context提前退出
        auto work1 = make_work_guard(ioContext1);
        auto work2 = make_work_guard(ioContext2);

        // 启动工作线程
        std::vector<std::thread> threads;
        threads.emplace_back(worker, std::ref(ioContext1));
        threads.emplace_back(worker, std::ref(ioContext2));

        trace("App started:", std::thread::hardware_concurrency());

        // 运行5秒后停止程序
        std::this_thread::sleep_for(5s);
        running = false;
        // 主动停止io_context,确保线程能退出
        ioContext1.stop();
        ioContext2.stop();

        // 等待线程结束
        for (auto& thread : threads) {
            thread.join();
        }

        trace("All worker threads joined.");
    } catch (std::exception const& e) {
        trace("Exception:", std::quoted(e.what()));
    }
}

关键修复点

  1. 智能指针管理对象生命周期:用std::shared_ptr包裹steady_timer,确保handler捕获的对象在异步操作完成前不会被销毁,彻底避免悬空引用问题。
  2. 添加退出控制机制:用std::atomic_bool标记运行状态,配合io_context::stop()主动终止未完成的异步操作,确保程序能正常退出。
  3. 替换阻塞调用为异步延迟:用asio::steady_timer的异步等待替代usleep,遵循异步编程模型,避免阻塞io_context线程导致的调度异常。
  4. 主动停止io_context:通过io_context::stop()强制终止任务队列,让线程的run()方法能正常退出,避免无限阻塞。

嵌入式系统优化建议

针对你的双核Cortex A7硬件和嵌入式Linux环境,额外建议:

  • 控制异步任务的数量,避免任务队列过长占用过多内存。
  • 尽量减少跨线程投递任务的频率,降低线程间同步开销。
  • 定期检查系统资源(如内存、线程栈),防止资源耗尽引发异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 14:23:11