From cde79d8aa25d34ca4af615d1adf349720e24a94a Mon Sep 17 00:00:00 2001 From: Nick Child Date: Tue, 8 Sep 2026 11:28:15 -0400 Subject: [PATCH] fix(client): Avoid missing final send CQE Swap the order of the atomic_inc and the ib_req_notify_cq when in a send CQ notify callback. Otherwise, there is a possible race with polling the last CQE and re-arming the IB_CQ_NEXT_COMP flag. For example, previously the following series of events was possible: 1. In polling thread, CQE X is polled off the queue 2. In the notify callback thread, the notify for X arrives, it increments the atomic 3. In polling thread: capture atomic, do empty poll, start waiting 4. In RDMA provider thread: Enqueue CQE Y, IB_CQ_NEXT_COMP is not yet set, so don't issue a notify callback 5. In X's notify callback thread, we issue ib_req_notify_cq and wake 6. In poll thread; Is awoken but the waiter's predicate is false, sendCompEventCount is unchanged from step 3, so it sleeps again. 7. Wait with notify armed and and an entry waiting to be polled in the CQE. Eventually timeout. This is a very tight race window but is rather common if the RDMA provider serializes the CQ enqueue, poll, and notify operations (which OPA does). The alternative and proper fix is to implement IB_CQ_REPORT_MISSED_EVENTS, but that would require a larger code overhaul. Signed-off-by: Nick Child --- client_module/source/common/net/sock/ibv/IBVSocket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client_module/source/common/net/sock/ibv/IBVSocket.c b/client_module/source/common/net/sock/ibv/IBVSocket.c index 9f4a83c3..589bc556 100644 --- a/client_module/source/common/net/sock/ibv/IBVSocket.c +++ b/client_module/source/common/net/sock/ibv/IBVSocket.c @@ -1918,12 +1918,12 @@ void __IBVSocket_sendCompletionHandler(struct ib_cq *cq, void *cq_context) IBVCommContext* commContext = _this->commContext; int reqNotifySendRes; - atomic_inc(&commContext->sendCompEventCount); - reqNotifySendRes = ib_req_notify_cq(commContext->sendCQ, IB_CQ_NEXT_COMP); if(unlikely(reqNotifySendRes) ) ibv_print_info("Couldn't request CQ notification\n"); + atomic_inc(&commContext->sendCompEventCount); + wake_up(&commContext->sendCompWaitQ); }