已开启
[缺陷] 双SP686C RAID卡MCTP通信失败:worker线程与smld线程跨lua_State竞态 #453
huangminghao创建于 8月7日
openUBMC-robot
8月7日 评论:
8月7日 评论:
8月7日 添加了label:sig/sig-hardware
8月7日 将 WeberChen 设为负责人
openUBMC-robot
8月7日 评论:
8月7日 评论:
欢迎来到 openUBMC 社区
Hey @yelmh , 感谢你对社区的贡献.
机器人使用手册
有关指令的使用,可以点击 说明文档 或 论坛 查看详情。开发人员可以在每个PR或Issue下方评论特定指令来触发机器人任务。
联系指引
有疑问可以联系 SIG: sig-hardware ,
维护者是: @changxingOpenUBMC, @nathanael, @xiaoxinglxs, @yelvsub ,
优秀贡献者是: @dli_bmc, @weiziang, @yelmh .


openUBMC-robot
8月7日 评论:
8月7日 评论:
Issue 工作流介绍
社区的需求和缺陷的工作流状态处于纳管中。
| 类型 | 上个状态 | 下个状态 | 评论命令 | 谁可以操作 |
|---|---|---|---|---|
| 需求 | 待办的 | 已接纳 | /todo2accepted | SIG组: sig-release-management (maintainer) |
| 需求 | 已接纳 | 开发中 | /accepted2developing | 仓库成员角色: Maintainer, Committer, Contributor, Owner |
| 需求 | 开发中 | 转测中 | /developing2testing | 仓库成员角色: Maintainer, Committer, Contributor, Owner |
| 需求 | 转测中 | 待验收 | /testing2UAT | 仓库成员角色: Maintainer, Committer, Contributor, Owner |
| 需求 | 待验收 | 已完成 | /UAT2done | SIG组: sig-QA (maintainer,committer) |
| 需求 | 待办的 | 已挂起 | /todo2suspended | SIG组: sig-release-management (maintainer) |
| 需求 | 已挂起 | 已接纳 | /suspended2accepted | SIG组: sig-release-management (maintainer) |
| 需求 | 待办的 | 已拒绝 | /todo2rejected | SIG组: sig-release-management (maintainer) |
| 需求 | 已拒绝 | 已接纳 | /rejected2accepted | SIG组: sig-release-management (maintainer) |


8月7日 修改了issue 的描述
8月7日 关联了pull request:feat: test
8月7日 issue类型由 需求 改变为 缺陷
8月7日 修改了issue 的描述
8月7日 关联了pull request:fix: 修复双RAID卡场景概率出现带外通信异常的问题
huangminghao
9月14日 评论:
9月14日 评论:
/todo2fixing


9月14日 issue状态由 待修复 改变为 修复中
huangminghao
9月14日 评论:
9月14日 评论:
/fixing2UAT


9月14日 issue状态由 修复中 改变为 待验收
HuaKun_caoluyang
18 天前 评论:
18 天前 评论:
200 次 AC 上下电必现么,为什么是200次,好奇怪


环境信息
src/lualib/sml/init.lua、sml_callbacks.lua、include/hwproxy/plugins/sml/cmds.lua)问题详细描述
https://discuss.openubmc.cn/t/topic/6643
预置条件
worker.new(1)创建,加载sml_callbacks.lua模块操作步骤
init.lua调用worker.new(1)创建独立 OS 线程(拥有独立的lua_State,记为 L_worker)sml.callback:start_module('sml.sml_callbacks')在 worker 线程中加载sml_callbacks.luainit.lua通过sml.callback:send('install_mctp_writeread_cb_X', true)向 worker 线程发送消息cbs:set_mctp_writeread_cb(ctrl_id, mctp_writeread),底层执行luaL_ref(L_worker)将回调注册到 L_worker 的 registryref_value机制捕获m_L = main_thread(L_worker)(即 L_worker 的主线程引用)register_controller)时,C++ sml_core 库通过lua_rawgeti(m_L, ref)+lua_pcall(m_L, ...)调用回调lua_pcall从 smld OS 线程执行,但操作的 lua_State 是 L_worker → 跨线程竞态结果描述
实际结果: 双 SP686C RAID 卡场景下,MCTP 通信间歇性失败,200 次 AC 上下电必现。worker 线程与 smld 线程同时操作同一个
lua_State(L_worker),导致 Lua 栈/registry 损坏,MCTP 读写回调执行异常。预期结果: MCTP 通信稳定可靠,多 RAID 卡场景下无间歇性失败。
问题影响
问题定位情况
根因分析
问题根因是 worker 线程与 smld 线程跨
lua_State竞态:worker.new(1)创建独立 OS 线程,拥有独立的lua_State(L_worker)sml_callbacks.lua在 worker 线程中执行cbs:set_mctp_writeread_cb(ctrl_id, mctp_writeread),底层调用luaL_ref(L_worker)将回调注册到 L_worker 的 registryref_value机制捕获m_L = main_thread(L_worker)(L_worker 的主线程)lua_rawgeti(m_L, ref)+lua_pcall(m_L, ...)调用回调lua_State→ 两个线程同时操作同一个lua_State的栈和 registry → 栈损坏/崩溃/MCTP 通信失败关键代码路径:
src/lualib/sml/init.lualine 37:local sml = setmetatable({ callback = worker.new(1) }, sml_mt)— 创建 worker 线程src/lualib/sml/init.lualine 53-55:sml.callback:send(mctp_ctrl_map[ctrl_idx], true)— 发送注册消息到 worker 线程src/lualib/sml/sml_callbacks.lualine 67-68:cbs:set_mctp_writeread_cb(tonumber(...), mctp_writeread)— 在 L_worker 上执行 luaL_refref_value构造时luaL_ref(L_worker)+ 捕获m_L = main_thread(L_worker),执行时lua_rawgeti(m_L)+lua_pcall(m_L)— 从 smld 线程操作 L_worker建议解决方案
将 MCTP 读写回调的注册和执行统一到 smld 线程的
lua_State(L_smld),消除跨线程竞态:init.lua中删除worker.new(1)、__gc、start_module('sml.sml_callbacks')do_mctp_writeread/mctp_writeread函数从sml_callbacks.lua迁移到include/hwproxy/plugins/sml/cmds.lua(smld 线程代码)cmds.lua中新增CMD.set_mctp_writeread_cb(ctrl_id),调用cbs:set_mctp_writeread_cb(ctrl_id, mctp_writeread)init.lua中将sml.callback:send(...)改为skynet.call('.smld', 'lua', 'set_mctp_writeread_cb', ctrl_idx)修复后效果:
luaL_ref和lua_pcall都在 smld 线程的 L_smld 上执行,彻底消除跨线程竞态skynet.call保证回调注册完成后再执行后续命令(旧代码worker:send与 smld 命令处理无顺序保证)ep:Request)始终在 smld 线程执行(旧设计中也是如此),移除 worker 不改变阻塞行为关联 PR: https://gitcode.com/openUBMC/storage/pull/507
临时规避方案
无临时规避方案,需通过代码修复消除跨线程竞态。
附件
src/lualib/sml/init.luasrc/lualib/sml/sml_callbacks.luainclude/hwproxy/plugins/sml/cmds.lua