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

Boost TCP Socket无限阻塞排查:he-transformer库通信异常调试

问题分析与修复方案

核心问题

服务器阻塞的根本原因是:客户端收到结果后立即关闭连接,导致服务器正在进行的async_write操作触发网络错误,但服务器的错误处理直接抛出异常中断流程,既没有清理未完成的消息队列,也没有通知等待中的条件变量,使得服务器的writing_cond.wait()永远无法被唤醒。

另外,is_writing仅通过消息队列是否为空判断写入状态,但异步写失败时队列未被正确清空,进一步加剧了阻塞问题。

具体修复步骤

1. 修复服务器异步写的错误处理逻辑

修改TCPSession::do_write()中的async_write回调,不再直接抛出异常,而是处理错误并正确清理状态:

boost::asio::async_write(
    m_socket, boost::asio::buffer(m_write_buffer),
    [this, self](boost::system::error_code ec, std::size_t /* length */) {
      if (ec) {
        NGRAPH_HE_LOG(1) << "Server error writing message: " << ec.message();
        // 清空消息队列,避免后续误判写入状态
        std::lock_guard<std::mutex> lock(m_queue_mutex);
        m_message_queue.clear();
        // 通知所有等待的线程,写入已结束(无论成功失败)
        m_is_writing.notify_all();
        return;
      }
      std::lock_guard<std::mutex> lock(m_queue_mutex);
      m_message_queue.pop_front();
      if (!m_message_queue.empty()) {
        do_write();
      } else {
        m_is_writing.notify_all();
      }
    });

原因:当客户端提前关闭连接时,async_write会返回错误,此时必须清空队列并通知条件变量,让服务器的等待逻辑能正常退出。

2. 确保is_writing的判断线程安全

检查is_writing()的实现,必须加锁访问m_message_queue:

bool TCPSession::is_writing() const {
  std::lock_guard<std::mutex> lock(m_queue_mutex);
  return !m_message_queue.empty();
}

原因:原代码如果没加锁,在多线程环境下读取队列状态会有竞态条件,导致判断不准确。

3. 调整客户端关闭时机(可选)

如果希望客户端更优雅关闭,可以延迟调用close_connection(),确保服务器所有响应都已接收完成。比如在客户端的消息处理逻辑中,确认所有预期的张量都已收到后再关闭:

void HESealClient::handle_result(const pb::TCPMessage& message) {
    // ... 处理结果逻辑 ...

    // 确认所有结果都已接收后再关闭
    if (all_results_received()) {
        close_connection();
    }
}

原因:避免客户端在服务器还在发送数据时就关闭连接,减少触发网络错误的概率。

4. 优化服务器等待逻辑的超时机制(可选)

为服务器的writing_cond.wait()添加超时,防止极端情况下永久阻塞:

// Wait until message is written or timeout after 5 seconds
std::unique_lock<std::mutex> mlock(m_result_mutex);
std::condition_variable& writing_cond = m_session->is_writing_cond();
bool success = writing_cond.wait_for(mlock, std::chrono::seconds(5), 
                                     [this] { return !m_session->is_writing(); });
if (!success) {
    NGRAPH_HE_LOG(1) << "Server timed out waiting for write completion";
    // 可以选择强制清理会话
    m_session->close();
}

原因:增加容错性,即使前面的修复没覆盖所有场景,也能避免服务器永久挂起。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 13:18:02