Replace NL_KEEP code with proper message reference counting
Adds reference counting to netlink messages so callbacks
can hold on to a message without using the broken keep
message flag.
diff --git a/lib/msg.c b/lib/msg.c
index ad6f5a1..d08d057 100644
--- a/lib/msg.c
+++ b/lib/msg.c
@@ -372,6 +372,8 @@
if (!nm)
goto errout;
+ nm->nm_refcnt = 1;
+
nm->nm_nlh = malloc(len);
if (!nm->nm_nlh)
goto errout;
@@ -645,21 +647,39 @@
}
/**
- * Free a netlink message
- * @arg n netlink message
- *
- * Destroys a netlink message and frees up all used memory.
- *
- * @pre The message must be unused.
+ * Acquire a reference on a netlink message
+ * @arg msg message to acquire reference from
*/
-void nlmsg_free(struct nl_msg *n)
+void nlmsg_get(struct nl_msg *msg)
{
- if (!n)
+ msg->nm_refcnt++;
+ NL_DBG(4, "New reference to message %p, total %d\n",
+ msg, msg->nm_refcnt);
+}
+
+/**
+ * Release a reference from an netlink message
+ * @arg msg message to release reference from
+ *
+ * Frees memory after the last reference has been released.
+ */
+void nlmsg_free(struct nl_msg *msg)
+{
+ if (!msg)
return;
- free(n->nm_nlh);
- free(n);
- NL_DBG(2, "msg %p: Freed\n", n);
+ msg->nm_refcnt--;
+ NL_DBG(4, "Returned message reference %p, %d remaining\n",
+ msg, msg->nm_refcnt);
+
+ if (msg->nm_refcnt < 0)
+ BUG();
+
+ if (msg->nm_refcnt <= 0) {
+ free(msg->nm_nlh);
+ free(msg);
+ NL_DBG(2, "msg %p: Freed\n", msg);
+ }
}
/** @} */