已关闭
[Bug-Report|缺陷反馈]: CcuKernelMgr::GetKernel 并发读取 kernelMap_ 时同步保护可能不足 #286
MBpanzz创建于 6月24日关闭于 7月8日
Leewis
7月8日 评论:
7月8日 评论:
您好,相关问题已合入,当前issue将闭环,后续有相关问题欢迎提交issue交流讨论。
https://gitcode.com/cann/hcomm/pull/3119


7月8日 添加了label:resolved
您好,相关问题已合入,当前issue将闭环,后续有相关问题欢迎提交issue交流讨论。
https://gitcode.com/cann/hcomm/pull/3119


Thanks for sending an issue! Please fill in the following template to help quickly solve your problem.
Describe the current behavior / 问题描述 (Mandatory / 必填)
在
CcuKernelMgr::GetKernel()中,函数直接读取成员变量kernelMap_而未加锁保护。同时UnRegister()在互斥锁kernelMapMutex_的保护下对kernelMap_执行节点删除操作。异常回调路径CcuTaskException::InitChannelMap在另一把全局锁g_channelMapMutex下调用GetKernel(),但该锁与kernelMapMutex_不同,不能防止对kernelMap_的并发访问。当异常回调线程与主线程的
UnRegister()并发执行时,GetKernel()可能读到处于中间状态的unordered_map,存在未定义行为的风险。此外,GetKernel()返回的是CcuKernel裸指针,若调用侧在锁外使用该指针而同一时刻UnRegister()已销毁对应的unique_ptr,可能出现 use-after-free。相关的代码路径:
GetKernel(读取端,无锁):
// ccu_kernel_mgr.cc:730 CcuKernel *CcuKernelMgr::GetKernel(const CcuKernelHandle kernelHandle) { auto it = kernelMap_.find(kernelHandle); // ← 无锁读取 if (it == kernelMap_.end()) { return nullptr; } return it->second.get(); // ← 返回裸指针,锁外使用 }UnRegister(删除端,持 kernelMapMutex_):
// ccu_kernel_mgr.cc:548-561 CcuResult CcuKernelMgr::UnRegister(const CcuKernelHandle kernelHandle) { std::unique_lock<std::mutex> lock(kernelMapMutex_); ... kernelMap_.erase(kernelHandle); // ← 销毁 unique_ptr,回收 kernel 对象 return CcuResult::CCU_SUCCESS; }异常回调路径调用 GetKernel(持另一把锁):
// ccuTaskException.cc:228-235 HcclResult CcuTaskException::InitChannelMap(s32 deviceId, u64 ccuKernelHandle) { std::lock_guard<std::mutex> lock(g_channelMapMutex); // 全局锁,非 kernelMapMutex_ auto &kernelMgr = hcomm::CcuKernelMgr::GetInstance(deviceId); auto *kernel = kernelMgr.GetKernel(ccuKernelHandle); // ← 无锁读 kernelMap_ ... }GetKernel 在 Launch 路径上的调用(同线程,安全):
// ccu_launch.cc:304-306 const uint32_t devLogicId = HcclGetThreadDeviceId(); auto &kernelMgr = hcomm::CcuKernelMgr::GetInstance(devLogicId); auto *kernel = kernelMgr.GetKernel(kernelHandle); // 与 Register 同线程,当前安全Environment / 环境信息 (Mandatory / 必填)
该问题与特定运行环境无关
Steps to reproduce the issue / 重现步骤 (Mandatory / 必填)
HcommCcuKernelLaunch及后续的CcuInstance析构以触发 UnRegisterCcuTaskException::ProcessCcuException被频繁调用GetKernel()和UnRegister()入口处添加 ThreadSanitizer 或std::atomic_thread_fence检测,编译并运行kernelMap_相关的 data race 或 use-after-free 报告Describe the expected behavior / 预期结果 (Mandatory / 必填)
GetKernel()不应与UnRegister()并发访问同一kernelMap_Related log / screenshot / 日志 / 截图 (Mandatory / 必填)
无
Special notes for this issue/备注 (Optional / 选填)
无