已关闭
[Bug-Report|缺陷反馈]: x86 默认开启 ASAN 导致 UT 编译阶段 gen_esb 崩溃,--asan=false 因脚本缓存陈旧不生效 #466
gothizzz创建于  6月25日关闭于  7月3日
gothizzz
gothizzz
6月25日 创建

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

[x] 我已经搜索过现有和历史issues,确认这是一个新问题

问题描述

在 openEuler 24.03 LTS(x86_64)环境下,按 docs/zh/build.md 执行 UT:

bash tests/run_test.sh --ut=ge_common

UT 在编译阶段即失败,无法生成任何测试可执行文件,0 用例执行。失败发生在测试框架的代码生成步骤 generate_es_ut_test_code,根因为 gen_esb 在 ASAN 下发生段错误(AddressSanitizer: nested bug)。

run_test.sh 在 x86 架构下默认自动开启 ASANENABLE_ASAN=true,见 tests/run_test.sh 第 567-571 行),因此该问题是 x86 环境 UT 的默认行为,外部开发者按文档直接执行即可复现。

复现步骤

  1. openEuler 24.03 LTS x86_64 容器,按 docs/zh/build.mdscripts/init_env.sh 安装 CANN Toolkit 9.1.0 及全部依赖(gcc 12.3.1 / cmake 3.27.9 / python 3.11 等,scripts/check_env.sh 26 项 PASS)。
  2. source /usr/local/Ascend/cann/set_env.sh
  3. bash tests/run_test.sh --ut=ge_common -j12

期望

UT 编译完成并执行测试用例,或在 ASAN 下检测到问题时给出清晰的可重试/可定位信息。

实际

[2026-06-24 17:31:42] [ES-GEN] [Attempt 1/10] Executing gen_esb...
[2026-06-24 17:31:42] [ES-GEN] Command: ASCEND_OPP_PATH=.../opp_standard_path_stub_geir_ops LD_PRELOAD=/usr/lib/gcc/x86_64-openEuler-linux/12/libasan.so ".../gen_esb" --output_dir=... --module_name="ut_test" --exclude_ops=""
AddressSanitizer:DEADLYSIGNAL
==125770==ERROR: AddressSanitizer: SEGV on unknown address 0x631eb5e7e680 (pc 0x74ad87bd4d9f ...) (READ memory access)
AddressSanitizer: nested bug in the same thread, aborting.
[2026-06-24 17:31:42] [ES-GEN] [Non-retriable] Exit code 1
make[3]: *** [.../generate_es_ut_test_code.dir/build.make:80: .../generated_code.flag] Error 1
GraphEngine build failed.

注意:

  • generate_es_ge_test_code(输入 opp_standard_path_test_ops_proto)在相同 ASAN 配置下成功生成了 142 个算子;
  • generate_es_ut_test_code(输入 opp_standard_path_stub_geir_ops失败
  • 即同一 gen_esb 二进制、同一 LD_PRELOAD,仅 OPP 输入不同 → gen_esb 处理 stub_geir_ops 数据时存在被 ASAN 捕获的内存缺陷。

根因分析

  1. cmake/generate_es_package.cmake 生成的 build_ut/cmake/run_gen_esb_with_lock.sh 中,当 ENABLE_ASAN=true 时会对 gen_esb 执行 LD_PRELOAD=$(gcc -print-file-name=libasan.so)(第 286-289 行),用于给 gen_esb 链接的、带 -fsanitize=address 编译的依赖库(如 libgraph.so)提供 ASAN 运行时。
  2. gen_esb 自身(compiler/graph/eager_style_graph_builder/es_generator/CMakeLists.txt)使用 ${AIR_COMMON_COMPILE_OPTION} 编译,未带 -fsanitize=addressbuild_ut/.../gen_esb.dir/flags.make 无 fsanitize)。
  3. objdump -p 显示 gen_esb 及其依赖 libgraph.soNEEDED 列表中均无 libasan,libasan 仅通过 LD_PRELOAD 注入。
  4. 在处理 stub_geir_ops 输入时触发 SEGV,ASAN 报 "nested bug in the same thread, aborting",退出码为 1
  5. run_gen_esb_with_lock.sh 的重试逻辑(第 299-313 行)只对退出码 139(SIGSEGV)/126/127 重试,退出码 1 被判定为 [Non-retriable] 直接放弃 → 编译失败。

附带问题:--asan=false 不生效(脚本缓存陈旧)

run_gen_esb_with_lock.shif (NOT EXISTS ${ES_LOCK_SCRIPT}) 保护(generate_es_package.cmake 第 185 行),仅在首次 cmake 配置时生成一次,ASAN 开关被烘焙进脚本内容。因此:

  • 先以默认(ASAN=true)配置过 build_ut 后,再执行 bash tests/run_test.sh --ut=ge_common --asan=false 时,脚本不会被重新生成,LD_PRELOAD libasan 依然生效,--asan=false 形同虚设;
  • 必须手动 rm -rf build_ut(或删除 build_ut/cmake/run_gen_esb_with_lock.sh)才能让 --asan=false 真正生效。

环境信息

  • OS:openEuler 24.03 LTS(x86_64)
  • GCC:12.3.1,CMake:3.27.9,Python:3.11.6,bash:5.2.15
  • CANN Toolkit:9.1.0(master 分支构建)
  • 仓库:https://gitcode.com/cann/ge.git (master)
  • scripts/check_env.sh:26 PASS / 1 ERROR(lcov,可选) / 2 WARNING

影响

  • x86 架构下 bash tests/run_test.sh --ut=* 默认即失败,外部开发者无法按文档完成 UT 验证;
  • --asan=false 因脚本缓存陈旧无法作为有效规避手段;
  • 同类 ASAN 退出码 1(nested bug)不受重试逻辑覆盖。

期望的修复方向(建议)

  1. 排查 gen_esb 处理 stub_geir_ops 时的内存缺陷(根因);
  2. run_gen_esb_with_lock.shENABLE_ASAN 变化时重新生成(消除缓存陈旧),使 --asan=false 可靠生效;
  3. 重试逻辑考虑覆盖 ASAN "nested bug" 退出码,或在 ASAN 场景下提供更可定位的报错。
likedislike
gothizzzgothizzz
6月25日 添加了label:buginfra-tooling
gothizzzgothizzz
6月25日 关联了pull request:fix(cmake): ENABLE_ASAN 变化时重新生成 es lock 脚本,修复 --asan=false 缓存陈旧
gothizzzgothizzz
6月25日 关联了pull request:docs: 标注 lcov 可选、UT 补充 ASAN 默认开启提示、Dockerfile 升级至 ubuntu22.04
GengChao
GengChao成员
6月25日 评论:

感谢你的提问和修复,很好的问题,尝试解答一下:

  1. 排查 gen_esb 处理 stub_geir_ops 时的内存缺陷(根因)-- 这个比较怀疑是asan本身的偶发问题,理由是generate_es_ge_test_code(输入 opp_standard_path_test_ops_proto)在相同 ASAN 配置下成功生成了 142 个算子; generate_es_ut_test_code(输入 opp_standard_path_stub_geir_ops)失败。 对于gen_esb来说,就是一个简单的代码生成工具,从原型so读原型生成对应为代码,只有喂的原型so差异不会导致一个SEGV一个正常,所以可以多尝试几次看看(尝试的方式可以参考第三点本地手动改一下run_gen_esb_with_lock.sh的脚本,让其判断返回值为1自动重试)
  2. run_gen_esb_with_lock.sh 在 ENABLE_ASAN 变化时重新生成(消除缓存陈旧),使 --asan=false 可靠生效 --可以优化,看到你已经提了优化pr,感谢~
  3. 重试逻辑考虑覆盖 ASAN "nested bug" 退出码-- 这个可以针对1的返回值添加重试,避免本地asan库本身的偶先问题,这个后续我来提交一个pr修复
likedislike
夏国正成员
6月25日 将 gothizzz 设为负责人
夏国正成员
6月25日 移除了负责人 gothizzz
夏国正成员
6月25日 将 kobemini 设为负责人
GengChaoGengChao成员
6月27日 关联了pull request:fix: gen_esb 脚本使用单文件 sync 替换全局 sync 避免长时间阻塞
GengChao
GengChao成员
6月30日 评论:

问题2,3已经在pr修复,问题1可以重试一下

likedislike
夏国正成员
7月3日 issue状态由 进行中 改变为 已完成
此处折叠了10条事件消息 查看更多
Wwangbin成员
7月7日 删除了关联的pull request:【PR】: 简要描述 解决文档描述相关issues问题