问题描述
当前通过mctp_lib这个库的get_endpoint_and_transport来创建endpoint时会一直卡住,不会超时退出也没报错。通过log可看到start 3有打印,start 4一直没打印;
具体的代码逻辑如下:
求助内容:
1.get_endpoint_and_transport这个接口是否有超时的机制呢?
2.当前代码中phy_addr对应的pcie设备不存在的情况下,该接口也没报错,是否也不正常?
答案内容由AI生成,仅供参考:
| 问题 | 结论 | 建议 |
|---|---|---|
get_endpoint_and_transport 是否有超时机制? |
无内置超时机制,可能导致永久阻塞 | 添加外部超时控制 |
| 设备不存在时不报错是否正常? | 不正常,应提前校验并返回错误 | 调用前检查设备存在性 |
| 如何定位问题? | 使用 tracemctp 查看通信过程 |
启用调试命令辅助分析 |
| 长期解决方向? | 接口缺乏鲁棒性 | 推动增加超时和异步支持 |
最终建议:在调用
get_endpoint_and_transport前,务必校验设备存在性 + 添加外部超时机制,以规避当前接口的设计局限。
get_endpoint_and_transport 接口的超时机制与异常行为分析根据您提供的上下文信息,以下是针对您提出的两个问题的详细分析与解答。
get_endpoint_and_transport 接口是否有超时机制?**结论:当前 get_endpoint_and_transport 接口在调用过程中 **(MCTP over PCIe)
mctpd 服务管理 MCTP 通信生命周期
mctpd 是 OpenUBMC 中负责管理 MCTP 协议通信的核心服务,它通过 mctp_lib 提供的接口(如 get_endpoint_and_transport)来创建和管理 MCTP Endpoint 和 Transport 对象。
mctpd 支持对 MCTP 请求设置超时机制,例如存在 MctpRequestTimeout 错误类型,表示 MCTP 请求超时(如参考文档 #5 所示:“kepler.mctpd.MctpRequestTimeout: The Mctp request timeout”)。
但 get_endpoint_and_transport 本身不保证内部操作有超时处理
尽管 MCTP 请求通信层具备超时能力,但从当前行为看,get_endpoint_and_transport 在等待远端设备响应或路由建立时可能会阻塞,且无内置超时退出机制。
您的日志中“start 3”已打印而“start 4”未打印,说明该函数调用处于永久阻塞状态,并未触发错误或返回,这表明:
系统为异步事件驱动架构,初始化依赖事件时序而非同步阻塞
上下文提到系统采用“System Asynchronous Event-Driven Architecture”,即组件初始化依赖事件触发而非顺序执行。
因此,get_endpoint_and_transport 可能在等待一个尚未发生的事件(如 PCIe 设备上线、mctpd 完成路由表构建),但由于未设置超时,最终造成无限等待。
结论:不正常 —— 若目标 PCIe 设备不存在,get_endpoint_and_transport 应返回明确错误或超时,而不是一直阻塞。
正确流程应包含设备可达性校验
该函数的工作流程包括:
phy_addr 定位远端 MCTP Endpoint;mctpd 请求创建对应的 Endpoint 和 Transport 对象;其中第 2 步应能检测到 phy_addr 是否有效。如果对应设备不存在(如 BDF 地址无实际硬件),则路由表中不应存在对应条目,此时应快速返回失败。
实际存在类似失败场景的日志记录
上下文日志(参考文档 #3)显示:
pcie_device ERROR : device_service.lua (342): [DeviceService] Can not find matching PCIeAddrinfo, PCIeDevice position = 00 DeviceType = 26 SlotID = 1
这表明系统在尝试查找 PCIe 地址信息失败时会明确记录错误。说明系统具备检测“设备未匹配”的能力。
当前无报错 + 无限等待 = 存在设计缺陷或配置问题
结合上述日志和行为分析,get_endpoint_and_transport 在设备不存在时仍卡住,属于以下一种或多种情况:
get_pcie_device_info() 或 D-Bus 查询 PCIe 设备列表);使用 Lua 的异步任务或定时器机制,避免阻塞主线程:
local function register_pcie_endpoint_with_timeout(bus, bus_num, dev_num, func_num, timeout_sec)
local timeout_occurred = false
local timer = setTimeout(timeout_sec * 1000, function()
timeout_occurred = true
log:error("get_endpoint_and_transport timeout after %d seconds", timeout_sec)
end)
local success = false
local co = coroutine.create(function()
local ok, phy_addr = pcall(mctp_lib.bdf_to_phy_addr, bus_num, dev_num, func_num)
if not ok then
log:error('bdf to phy addr failed')
return
end
-- 使用非阻塞方式或后台任务尝试获取 endpoint
local ok2, endpoint, transport = pcall(mctp_lib.get_endpoint_and_transport, bus, "yctco_app", phy_addr, MSG_TYPE_VDPCI)
if timeout_occurred then return end
clearTimeout(timer)
if not ok2 or not endpoint or not transport then
log:error('get_endpoint_and_transport failed')
else
log:notice("Endpoint created successfully")
success = true
end
end)
resume(co) -- 启动协程
end
注意:需确认当前 Lua 环境是否支持协程或异步任务机制。
在调用 get_endpoint_and_transport 前,先确认 PCIe 设备已识别:
local pci_device = c_nvme_mctp:get_pcie_device_info()
if not pci_device then
log:error("No matching PCIe device found for given position")
return
end
确保设备已在系统资源树中注册(如 /bmc/kepler/Systems/.../PCIeDevices/ 路径下可查)再进行 MCTP 连接。
使用 tracemctp 工具查看底层通信是否发出请求及是否有响应:
attach mctpd
tracemctp start
可判断:
参考文档 #6 提出新增
TraceMessage方法以打印报文,说明 缺乏调试手段是常见痛点。
向 mctp_lib 组件维护者提出以下改进建议:
get_endpoint_and_transport 增加可选超时参数;NO_ROUTE_TO_HOST);get_endpoint_and_transport_async);| 问题 | 结论 | 建议 |
|---|---|---|
get_endpoint_and_transport 是否有超时机制? |
无内置超时机制,可能导致永久阻塞 | 添加外部超时控制 |
| 设备不存在时不报错是否正常? | 不正常,应提前校验并返回错误 | 调用前检查设备存在性 |
| 如何定位问题? | 使用 tracemctp 查看通信过程 |
启用调试命令辅助分析 |
| 长期解决方向? | 接口缺乏鲁棒性 | 推动增加超时和异步支持 |
最终建议:在调用
get_endpoint_and_transport前,务必校验设备存在性 + 添加外部超时机制,以规避当前接口的设计局限。
这个接口是不存在超时的,底层是死等创建,一般通过fork个skynet协程去调用,接口不返回也不会有什么性能上的损耗。这个本来是确定有这个硬件才调用这个接口的。
如果期望超时退出可以用get_endpoint_and_transport_with_timeout接口,入参是bus, module_name, ep_info, timeout。bus, module_name和get_endpoint_and_transport一致,ep_info是字典,需要包含以下参数:
ep_info = {
phy_addr = phy_addr,
msg_type = msg_type,
position = position,
system_id = system_id
}
其中phy_addr和msg_type必填;position为smbus协议才有的,pcie协议可以不填;system_id是主机id,选填,默认主机1。
timeout是超时时间,单位10ms,不填默认5分钟。