aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Prestwood <prestwoj@gmail.com>2023-05-18 09:47:15 -0700
committerDenis Kenzior <denkenz@gmail.com>2023-05-22 09:17:45 -0500
commit2bbedf57d2b861cde1716c61190fa4dcf3b2f512 (patch)
treea402e9c800a52e29a6c07a4b7f4c548a65e6c10a
parent2684f4b27f5ce16df00d2b3d13984c41ec9a5e5c (diff)
genl: fix l_genl_family_cancel to wait for NLMSG_DONE
If a genl request was already sent to the kernel a call to l_genl_family_cancel would remove it from the pending list immediately. This then allowed l_genl_family_send to queue another message before the previous/canceled message was completed. This is not how l_genl is intended to work. Instead we can clean up the request immediately in l_genl_family_cancel but not remove it from the queue. This will prevent any more messages from being sent until NLMSG_DONE was received for the canceled message.
-rw-r--r--ell/genl.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/ell/genl.c b/ell/genl.c
index 4ed95dfb..006edf29 100644
--- a/ell/genl.c
+++ b/ell/genl.c
@@ -1910,11 +1910,23 @@ LIB_EXPORT bool l_genl_family_cancel(struct l_genl_family *family,
if (request)
goto done;
- request = l_queue_remove_if(genl->pending_list, match_request_id,
+ request = l_queue_find(genl->pending_list, match_request_id,
L_UINT_TO_PTR(id));
if (!request)
return false;
+ /*
+ * A message in-flight still needs to wait for NLMSG_DONE so clean up
+ * for the caller but keep the request queued until its done.
+ */
+ if (request->destroy)
+ request->destroy(request->user_data);
+
+ request->callback = NULL;
+ request->destroy = NULL;
+
+ return true;
+
done:
destroy_request(request);