已关闭
[Bug-Report|缺陷反馈]: 服务端向多个 Endpoint 注册内存时,后续注册失败未回滚前序成功注册 #716
Polaris创建于  17 天前关闭于  13 天前
Polaris
17 天前 创建

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

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

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

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

问题描述

问题描述

HixlCSServer::RegisterMem 会依次向所有匹配的 Endpoint 注册同一块内存。当前实现中,如果前一个 Endpoint 注册成功,而后续 Endpoint 注册失败,HIXL_CHK_STATUS_RET 会直接返回错误,但此前已成功完成的 Endpoint 注册不会被注销或回滚。

相关代码路径

  • src/hixl/cs/hixl_cs_server.cc
  • HixlCSServer::RegisterMem
  • 失败返回点位于调用 endpoint->RegisterMem(...) 的循环内部

实际行为

接口返回失败,但底层仍保留部分成功注册状态。第一个 Endpoint 的注册句柄只存在于 HixlCSServer::RegisterMem 的局部 ep_mem_infos 中。由于函数在写入服务端 reg_mems_ 之前已经返回,调用方无法获得可用于 HixlCSServerUnregMem 的聚合句柄,因此无法通过正常公开接口清理这部分注册。

环境信息

HIXL 版本

  • 仓库:cann/hixl
  • Commit:884aad902480132a9ef3aadc73690e9fc53e590b

操作系统

Linux autodl-container-784e4d9ede-d72c02b7 5.4.0-144-generic
#161-Ubuntu SMP Fri Feb 3 14:49:04 UTC 2023 x86_64 GNU/Linux

编译环境

GCC:
gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0

CMake:
cmake version 4.1.3

重现步骤

1. 检出被测试版本

git checkout 884aad902480132a9ef3aadc73690e9fc53e590b

2. 应用复现测试补丁

修改以下 3 个测试相关文件:

tests/depends/hccl/src/hccl_stub.h
tests/depends/hccl/src/hccl_stub.cc
tests/cpp/hixl/cs/test_hixl_cs_server.cc

补丁内容包括:

  1. 为 HCCL Stub 增加 SetMemRegFailureOnCall,允许指定第 N 次
    HcommMemReg 返回指定错误;
  2. 统计 HcommMemReg 和 HcommMemUnreg 的调用次数;
  3. 统计当前仍处于注册状态的 Stub 句柄数量;
  4. 新增测试:
HixlCSTest.RegisterMemRollsBackEarlierEndpointsWhenLaterEndpointFails

测试创建两个 Host UBC_CTP Endpoint,并执行:

SetMemRegFailureOnCall(2U, HCCL_E_INTERNAL);

即:

  • 第一次 HcommMemReg 正常成功;
  • 第二次 HcommMemReg 返回 HCCL_E_INTERNAL。

随后调用 HixlCSServerRegMem,并检查:

EXPECT_EQ(GetMemRegCallCount(), 2U);
EXPECT_EQ(GetMemUnregCallCount(), 1U);
EXPECT_EQ(GetActiveMemRegCount(), 0U);

3. 加载 CANN 环境并运行 HIXL C++ Suite

source /usr/local/Ascend/cann/set_env.sh
bash tests/run_test.sh -t cpp -s hixl

测试目标能够正常构建,但新增测试失败。Suite 的退出码为 1,唯一失败项为:

HixlCSTest.RegisterMemRollsBackEarlierEndpointsWhenLaterEndpointFails

4. 定向运行复现测试

./build_test/tests/cpp/hixl/hixl_test \
  --gtest_filter=HixlCSTest.RegisterMemRollsBackEarlierEndpointsWhenLaterEndpointFails

连续执行 3 次,三次结果完全一致:

运行次数 退出码 HcommMemUnreg 实际/预期 活跃注册数实际/预期
1 1 0 / 1 1 / 0
2 1 0 / 1 1 / 0
3 1 0 / 1 1 / 0

问题可以稳定复现。

预期结果

RegisterMem 应保证失败原子性:任一 Endpoint 注册失败时,应回滚本次已成功注册的所有 Endpoint,确保接口返回失败后不残留注册状态;如果设计上无法回滚,则应返回可供调用方清理的句柄或信息。

日志 / 截图

实际失败日志

[ RUN      ] HixlCSTest.RegisterMemRollsBackEarlierEndpointsWhenLaterEndpointFails
[ERROR] GE(9052,ut):2026-09-16-18:29:06.931.080 [endpoint.cc:205][HIXL] 9052 RegisterMem: ErrorNo: 503900 Call api:HcommMemReg failed, ret:4, ep_handle:0xe, addr:0x55ff14acdb40, size:4 bytes
[ERROR] GE(9052,ut):2026-09-16-18:29:06.931.092 [hixl_cs_server.cc:346][HIXL] 9052 RegisterMem: ErrorNo: 503900 Failed to register mem.
[ERROR] GE(9052,ut):2026-09-16-18:29:06.931.097 [hixl_cs.cc:101][HIXL] 9052 HixlCSServerRegMem: ErrorNo: 503900 Failed to register server mem
test_hixl_cs_server.cc:296: Failure
Expected equality of these values:
  GetMemUnregCallCount()
    Which is: 0
  1U
    Which is: 1

test_hixl_cs_server.cc:297: Failure
Expected equality of these values:
  GetActiveMemRegCount()
    Which is: 1
  0U
    Which is: 0

[  FAILED  ] HixlCSTest.RegisterMemRollsBackEarlierEndpointsWhenLaterEndpointFails (0 ms)

日志证明:

  1. 第二次 Endpoint 注册按照测试配置失败;
  2. 第一次成功注册没有调用 HcommMemUnreg,实际注销次数为 0;
  3. 接口返回失败后仍有一个活跃注册句柄;
  4. 该问题连续运行 3 次均得到相同结果。

附件

04be92372b8a4ca3bac1a9ba8038df67.log
86b4fe138de7406895ef3dd39c692105.log

备注

likedislike
PPolaris
17 天前 issue类型由 任务 改变为 缺陷
Llining23666成员
16 天前 将 lining23666 设为负责人
lining23666成员
16 天前 评论:

感谢反馈,经代码检视确认该问题有效。

问题确认

HixlCSServer::RegisterMem(src/hixl/cs/hixl_cs_server.cc:322)在多 Endpoint 注册场景下确实缺少失败回滚:

  • 注册循环中任一 Endpoint 注册失败时,HIXL_CHK_STATUS_RET(hixl_cs_server.cc:346)直接返回错误,ep_mem_infos 中已成功注册的 Endpoint 不会被注销;
  • 聚合句柄仅在全部注册成功后写入 reg_mems_(hixl_cs_server.cc:358),失败路径下调用方无法通过 HixlCSServerUnregMem 清理残留注册。

影响评估

  • 残留注册在 Endpoint 销毁时由 Endpoint::Finalize 兜底清理(endpoint.cc:142),不会永久泄漏;但在 server 存续期间会占用 HCCL 侧注册资源,且调用方重试 RegisterMem 会造成重复注册,进一步放大资源占用;
  • client 侧仅向单个 local endpoint 注册(hixl_cs_client.cc:399),不受此问题影响。

修复方案

将采用失败原子性回滚:注册循环中任一 Endpoint 失败时,对本次已成功注册的 Endpoint 逐个执行 DeregisterMem 后再返回失败,与 Endpoint::RegisterMem 内部已有的回滚模式保持一致。同时会参考您提供的测试思路补充 UT(后续注册失败时校验 Unreg 调用次数与活跃注册数)。

修复 PR 会关联本 issue,欢迎继续关注与检视。

likedislike
Llining23666成员
16 天前 关联了pull request:[bugfix]: roll back registered endpoints when server RegisterMem fails (#716)
lining23666成员
16 天前 评论:

修复 PR 已提交:https://gitcode.com/cann/hixl/pull/1120 ,CI 已通过,欢迎检视。

likedislike
lining23666成员
15 天前 评论:

修复 PR 已合入:[bugfix]: roll back registered endpoints when server RegisterMem fails (#716)

likedislike
Llining23666成员
15 天前 添加了label:wait-feedback
Llining23666成员
15 天前 关联了pull request:[bugfix]: roll back registered endpoints when server RegisterMem fails
Llining23666成员
13 天前 issue状态由 待办的 改变为 已完成
Llining23666成员
13 天前 关闭了 issue
CANN-robotCANN-robot成员
13 天前 添加了label:resolved