Boost Asio SSL Strand内async_read+async_write执行失败问题排查
问题:Boost.Asio SSL流全双工异步读写线程安全问题
问题背景
我对Asio有一定使用经验,但无法在boost::asio::ssl::stream<boost::asio::ip::tcp::socket>上正确执行async_read和async_write操作,已编写最小复现代码。目标是在SSL流上实现全双工异步读写,按照文档要求将操作包裹在strand中,但仍出现线程安全问题。
环境与核心代码
环境为多线程io_context,socket持续收发数据,收发各有独立回调链,每个完成处理函数中调度下一次收发操作,所有逻辑均在strand内执行。核心代码如下:
std::function<void(bool, ssl::stream<tcp::socket>&, io_context::strand&, u64)> f = [&](bool send, ssl::stream<tcp::socket>& sock, io_context::strand& strand, u64 t) { strand.dispatch([&, send, t]() { std::vector<u8> buffer(10000); auto bb = mutable_buffer(buffer.data(), buffer.size()); auto callback = [&, send, t, buffer = std::move(buffer), moveOnly = std::unique_ptr<int>{}](boost::system::error_code error, std::size_t n) mutable { if (error) { std::cout << error.message() << std::endl; std::terminate(); } // 调度下一次操作或结束 if (t) f(send, sock, strand, t - 1); else --spinLock; }; if (send) async_write(sock, bb, std::move(callback)); else async_read(sock, bb, std::move(callback)); }); };
启动收发回调链的代码:
// 启动回调链 f(true, srvSocket, srvStrand, trials); f(false, srvSocket, srvStrand, trials); f(true, cliSocket, cliStrand, trials); f(false, cliSocket, cliStrand, trials);
问题现象
尽管使用了strand,OpenSSL内部仍出现线程不安全问题:运行时有时解密失败,有时直接在OpenSSL中崩溃。使用tcp::socket或单线程io_context时代码运行正常,已在Ubuntu和Windows环境测试。
解决方案
核心问题在于ssl::stream<tcp::socket>的执行上下文是多线程io_context,无法保证其始终在指定的strand上工作。ssl::stream本身不知道strand的存在,仅初始调用时在strand中执行,但底层socket回调后调度的读写操作不会自动落在指定strand上。
唯一可靠的解决方式是将strand作为执行上下文来构造SSL流,这样能确保所有与该流相关的异步操作都在strand的上下文中执行。
内容的提问来源于stack exchange,提问作者Peter Rindal
相关产品推荐
相关产品推荐

