如何避免陷入 rdma_get_recv_comp() 或 __ibv_get_cq_event()?

How to avoid getting stuck in rdma_get_recv_comp() or __ibv_get_cq_event()?

各位 RDMA 黑客,有人知道调用 __ibv_get_cq_event() 的 rdma_get_recv_comp() 是否会超时吗?

我的问题与此处显示的相同程序有关: RDMA program randomly hangs

它工作正常,但它对随机客户端断开连接不可靠。具体来说,如果我强行杀死客户端,那么服务器就会卡在 rdma_get_recv_comp() / ipv_get_cq_event().

这是针对 Mellanox ConnectX-3 的,我检查过默认超时为 2.14 秒,重试次数 = 1。但我不清楚 ibv_get_cq_event() 在阻塞模式下是否会超时。 ibv_modify_qp() 文档中对超时的解释似乎表明超时仅适用于发送 (rdma_get_send_comp()),因为只有发送方等待 ACK。但我认为允许接收超时也没有任何困难。

如果在这种情况下预期会挂在 rdma_get_recv_comp() 内,我该如何避免或实施超时?

一些可能性:

  1. 更改我的客户端关闭顺序,以便它执行所有必要的发送,这样它就不会在服务器上挂起 rdma_get_recv_comp()?

  2. 用轮询接收完成的循环替换 rdma_get_recv_comp()

ibv_get_cq_event()不超时。它等待完成事件(当工作请求完成并生成完成队列条目时生成)。如果没有生成任何事件,比如因为您的接收从未完成,那么您将永远等待。如果 QP(连接)转换到错误状态,那么所有发布的接收都将以刷新状态完成——但是如果你在轮询所有完成之前销毁 QP,那么它们将从 CQ 中删除。

所以你的问题可能是当客户端断开连接时,另一端不一定检测到断开连接——例如,如果客户端只是重新启动,那么 RDMA CM 不会干净地断开连接,如果服务器端没有在飞行中没有任何发送,它不会注意到断开连接。您可以通过某种保活来处理这个问题——0 字节 RDMA WRITE 对此很有效,因为它们是 NOP,但如果连接出现任何问题就会失败。

或者可能是您的服务器在收到来自 RDMA CM 的断开连接通知时急于销毁 QP。你想在你的连接结构上有一个引用计数,这样你就可以在销毁 QP 之前等待你要等待的一切。

最后,可以以非阻塞方式使用ibv_get_cq_event()。联机帮助页有一个在底层完成通道文件描述符上使用 poll() 来等待超时事件的示例。