diff options
author | James Prestwood <prestwoj@gmail.com> | 2023-05-18 09:47:15 -0700 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2023-05-22 09:17:45 -0500 |
commit | 2bbedf57d2b861cde1716c61190fa4dcf3b2f512 (patch) | |
tree | a402e9c800a52e29a6c07a4b7f4c548a65e6c10a | |
parent | 2684f4b27f5ce16df00d2b3d13984c41ec9a5e5c (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.c | 14 |
1 files changed, 13 insertions, 1 deletions
@@ -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); |