已关闭
[Bug-Report|缺陷反馈]: 代码存在注释与实现不一致、空指针等问题 #538
huchunmei_123创建于  27 天前关闭于  18 天前
huchunmei_123
27 天前 创建

在您提交issue前,请确认以下信息:

问题定位请提供通信两端报错日志!

CANN日志默认路径:$HOME/ascend/log/,若配置了ASCEND_PROCESS_LOG_PATHASCEND_WORK_PATH环境变量,则日志会落盘到指定路径下;

更多日志操作介绍请参考《日志简介》

问题描述

H1. 注释/日志说 [1, 10] 但实际校验 [1, 100]

  • 文件: src/llm_datadist/link_mgr/comm_entity.cc:204-205
  • 类别: 注释与实现不一致
constexpr int32_t kRetryCountMax = 100;  // 实际允许到 100
// 但错误消息说 "link_retry_count should be an integer between [1, 10]"

H2. 日志打印错误变量 — ret 而非 aclrt_ret

  • 文件: src/llm_datadist/link_mgr/comm_entity.cc:286, 297
  • 类别: 注释与实现不一致
auto aclrt_ret = aclrtStreamAbort(GetStream());
LLMLOGI("Call aclrtStreamAbort ret:%d.", ret);  // 应为 aclrt_ret

auto aclrt_ret = aclrtDestroyStream(GetStream());
LLMLOGI("Call aclrtDestroyStream ret:%d.", ret);  // 应为 aclrt_ret

H3. entity_map_[entity_id] 无 find 检查 — 潜在空指针

  • 文件: src/llm_datadist/link_mgr/comm_entity_manager.cc:39-40, 64
  • 类别: 空指针
  • 描述: 使用 operator[] 在 key 不存在时默认构造 shared_ptr(nullptr),随后直接 entity->GetPullMutex() 解引用。
auto entity = entity_map_[entity_id];  // nullptr if not found
std::lock_guard<std::mutex> pull_lock(entity->GetPullMutex());  // crash if nullptr

H4. UnloadSo 未重置所有函数指针 — 悬垂指针

  • 文件: src/llm_datadist/adapter_hccl/llm_hccl_adapter.cc:102-117
  • 类别: 悬垂指针
  • 描述: dl_hccl_batch_get_func_dl_hccl_comm_prepare_func_ 未置 nullptr,SO 卸载后调用会崩溃。dl_hccl_comm_prepare_func_ 加载时也缺少 LLM_CHECK_NOTNULL 校验。

H5. send_state.cc 日志参数与格式串不匹配

  • 文件: src/llm_datadist/fsm/send_state.cc:252-254
  • 类别: 注释与实现不一致
// 格式: "pull_size(%lu) > padded_cache_stride(%lu), block_size = %lu, cache_stride = %lu"
// 参数: request.pull_size, cache_entry.stride, request.block_size, request.block_size
//                                             ^应为 padded_size        ^应为 cache_entry.stride

H6. Reset() 不完整 — 统计字段残留旧值

  • 文件: src/llm_datadist/comm_statistic_manager.h:91-105, 122-129
  • 类别: 逻辑错误
  • 描述: SendStatisticInfo::Reset() 未重置 send_total_numsend_timessend_total_costsend_max_costsend_min_costRecvStatisticInfo::Reset() 同理。event_record_times = 0UL 还被重复写了两次。

H7. 非原子统计计数器多线程并发访问 — 数据竞争

  • 文件: src/llm_datadist/comm_statistic_manager.cc:18-24
  • 类别: 竞态条件
  • 描述: LinkStatisticInfoSendStatisticInfoRecvStatisticInfo 使用普通 uint64_t,被多个传输线程并发修改。仅 FuncStatisticInfo 使用了 atomic。

H8. uintptr_t%p 格式打印 — UB

  • 文件: src/llm_datadist/adxl/comm_channel.cc:636-637
  • 类别: 格式字符串
  • 描述: desc.local_addrdesc.remote_addruintptr_t(数值类型),用 %p(期望 void*)打印是未定义行为。

H9. timer_cnt 溢出不停止 — 继续创建 ID 冲突的定时器

  • 文件: src/llm_datadist/llm_datadist_timer.cc:62-64
  • 类别: 整数溢出 / 逻辑错误
  • 描述: timer_cnt == UINT32_MAX 时仅打印错误但不 return,继续用 UINT32_MAX 创建定时器,随后 ++timer_cnt 溢出为 0,下一个定时器复用正在使用的 ID。

H10. uint64_t%u 打印 — 截断

  • 文件: src/ops/hixl_kernel/hixl_batch_transfer.cc:84, 101
  • 类别: 格式字符串
  • 描述: op_list[i].lenuint64_t,用 %u 打印只显示低 32 位。>4GB 传输大小日志错误。

H11. Finalize 仅销毁 stream[0] — 资源泄漏

  • 文件: src/llm_datadist/cache_mgr/cache_manager.cc:543-546
  • 类别: 资源泄漏
  • 描述: InitCopyStreams(device_num) 可能创建多个 stream,但 Finalize() 只调用 DestroyCopyStream(0U)

H12. EnsureCopyStream 无越界检查

  • 文件: src/llm_datadist/cache_mgr/cache_manager.cc:548-554
  • 类别: 缓冲区溢出
  • 描述: copy_streams_[device_index] 未检查 device_index < copy_streams_.size()

H13. h2d_data_transfer_job.cc 未检查 ACL 返回值

  • 文件: src/llm_datadist/data_transfer/h2d_data_transfer_job.cc:229
  • 类别: 错误处理
  • 描述: aclrtQueryEventStatus 返回值被忽略,event_status 可能未初始化。

H14. Python switch_roleswitch_options=None 时崩溃

  • 文件: src/python/llm_datadist/llm_datadist/v2/llm_datadist.py:373
  • 类别: 空指针 / TypeError
  • 描述: check_isinstance 默认 allow_none=True 放行 None,但 "llm.listenIpInfo" in switch_options 对 None 操作抛 TypeError

H15. hixl.h GetNotifies 参数方向标注错误

  • 文件: include/hixl/hixl.h:167
  • 类别: 文档不一致
  • 描述: @param [in] notifies 应为 @param [out] notifies(非 const 引用,填充输出)。adxl_engine.h:128 中同名函数正确使用了 [out]

H16. llm_datadist.h 多个结构体 reserved 字段未初始化

  • 文件: include/llm_datadist/llm_datadist.h:108, 116, 125, 138, 145, 152
  • 类别: 未初始化内存
  • 描述: IpInfoClusterInfoCacheIndexCacheDescCacheKvCacheExtParamreserved[] 无默认初始化(= {}),而 RegisterCfg::reserved[128] = {0} 正确初始化了。不一致且存在信息泄露风险。

H17. SetRole 缺少 @param role 文档

  • 文件: include/llm_datadist/llm_datadist.h:185-189
  • 类别: 文档缺失
  • 描述: SetRole(LlmRole role, ...) 的 Doxygen 注释只文档了 @param optionsrole 参数完全未文档化。

环境信息

如上

重现步骤

如上

预期结果

如上

日志 / 截图

如上

备注

likedislike
zhaozhihui成员
27 天前 评论:

收到您的反馈,我们会尽快进行分析。

likedislike
Zzhaozhihui成员
27 天前 将 zhaozhihui 设为负责人
Zzhaozhihui成员
21 天前 关联了pull request:bugfix: 修复 listen_port 负数字符串解析提示(#539)
Zzhaozhihui成员
21 天前 关联了pull request:bugfix: 修复代码质量问题(#538)
zhaozhihui成员
21 天前 评论:

排查结论更新:

  • H1/H2/H3/H4/H5/H6/H7/H8/H13/H14/H15/H17 已提交独立 PR 处理:!880。
  • H9/H11/H12 按生产调用链确认后暂不纳入本次修改。
  • H10 当前基线代码已使用 %lu 打印 uint64_t 长度,无需额外修改。
  • H16 涉及 include/llm_datadist/llm_datadist.h 对外头文件中的 reserved 预留字段。该字段用于 ABI 预留,不作为当前接口语义读取或回填未初始化内容,本项排查无问题,不需要修改。
likedislike
zhaozhihui成员
21 天前 评论:

补充 H9/H11/H12 的生产调用链排查细节:

H9 timer_cnt 溢出

排查 LlmDatadistTimer::CreateTimer() 的生产调用点,当前只有两处:

  1. LLMDataDistV2::DoInnerInitialize() 创建统计 dump timer:
    DoInnerInitialize -> LlmDatadistTimer::Instance().Init() -> CreateTimer(...) -> StartTimer(...)
  2. adxl::StatisticManager::StartPeriodicDumpIfNeeded() 创建 ADXL 统计 dump timer:
    StartPeriodicDumpIfNeeded -> LlmDatadistTimer::Instance().Init() -> CreateTimer(...) -> StartTimer(...)

其中 ADXL 路径通过 dump_timer_handle_ != nullptr 防重复创建;LLMDataDistV2 在 DoInnerFinalize() 中会 StopTimer/DeleteTimer 已创建的统计 timer。该计数器达到 UINT32_MAX 需要 4,294,967,295 次成功创建 timer,当前生产调用链没有按请求、按任务或循环批量创建 timer 的路径,因此不构成实际问题,暂不修改。

H11 Finalize 只销毁 stream[0]

生产初始化路径为:

LLMDataDistV2::DoInnerInitialize -> DataCacheEngine::Initialize -> CacheManager::Initialize

CacheManager::Initialize() 中固定执行 copy_streams_.resize(1U)。生产释放路径为:

LLMDataDistV2::DoInnerFinalize/Finalize -> DataCacheEngine::Finalize -> CacheManager::Finalize -> DestroyCopyStream(0U)

因此生产路径只初始化 1 个 copy stream 槽位,也只需要销毁 stream[0]InitCopyStreams(size_t device_num) 当前在生产源码中没有调用点,属于内部预留/测试辅助入口,不影响现有生产释放链路。

H12 EnsureCopyStream 无越界检查

生产调用链为:

LLMDataDistV2::CopyCache -> DataCacheEngine::CopyCache -> CacheManager::CopyCache -> CopyCacheForContinuous/CopyCacheForBlocks -> EnsureCopyStream(device_index)

CopyCacheForContinuous()CopyCacheForBlocks()device_index 默认值均为 0UCacheManager::CopyCache() 调用这两个函数时没有传入第五个参数,因此生产路径固定使用 device_index=0。结合 CacheManager::Initialize() 固定 copy_streams_.resize(1U),不会出现访问越界。

结论:H9/H11/H12 按当前生产调用链确认无实际问题,本次不修改。

likedislike
Zzhaozhihui成员
21 天前 删除了关联的pull request:bugfix: 修复 listen_port 负数字符串解析提示(#539)
Zzhaozhihui成员
18 天前 issue状态由 进行中 改变为 已完成
Zzhaozhihui成员
18 天前 关闭了 issue
CANN-robotCANN-robot成员
18 天前 添加了label:resolved