[OpenWrt-Devel] [PATCH] libubus: handle NULL ubus_context in all sync requests by creating a local instance

Alexandru Ardelean ardeleanalex at gmail.com
Thu Jul 17 11:25:46 EDT 2014


This can serve as a convenience for sync requets, since no explicit
ubus_connect() + ubus_free() need to be done.

It can also help in cases where there are async + sync requests,
where one async request is working and sync calls are done.
Seems to create some weird races, probably because of possible
concurrent poll() calls on the same fd.

---
 libubus-obj.c | 42 +++++++++++++++++++++++++++++-------------
 libubus-req.c | 33 ++++++++++++++++++++++++++++-----
 libubus-sub.c | 15 +++++++++++++--
 libubus.c     | 48 ++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 112 insertions(+), 26 deletions(-)

diff --git a/libubus-obj.c b/libubus-obj.c
index 47bdb0a..29fe538 100644
--- a/libubus-obj.c
+++ b/libubus-obj.c
@@ -174,7 +174,13 @@ static bool ubus_push_object_type(const struct ubus_object_type *type)
 int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)
 {
 	struct ubus_request req;
-	int ret;
+	int ret = UBUS_STATUS_INVALID_ARGUMENT;
+	bool free_ctx = false;
+
+	if (!ctx)
+		free_ctx = (ctx = ubus_connect(NULL)) != NULL;
+	if (!ctx)
+		return -1;
 
 	blob_buf_init(&b, 0);
 
@@ -184,22 +190,24 @@ int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)
 		if (obj->type->id)
 			blob_put_int32(&b, UBUS_ATTR_OBJTYPE, obj->type->id);
 		else if (!ubus_push_object_type(obj->type))
-			return UBUS_STATUS_INVALID_ARGUMENT;
+			goto out;
 	}
 
 	if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_ADD_OBJECT, 0) < 0)
-		return UBUS_STATUS_INVALID_ARGUMENT;
+		goto out;
 
 	req.raw_data_cb = ubus_add_object_cb;
 	req.priv = obj;
 	ret = ubus_complete_request(ctx, &req, 0);
 	if (ret)
-		return ret;
+		goto out;
 
-	if (!obj->id)
-		return UBUS_STATUS_NO_DATA;
+	ret = (!obj->id) ? UBUS_STATUS_NO_DATA : 0;
+out:
+	if (free_ctx)
+		ubus_free(ctx);
 
-	return 0;
+	return ret;
 }
 
 static void ubus_remove_object_cb(struct ubus_request *req, int type, struct blob_attr *msg)
@@ -221,22 +229,30 @@ static void ubus_remove_object_cb(struct ubus_request *req, int type, struct blo
 int ubus_remove_object(struct ubus_context *ctx, struct ubus_object *obj)
 {
 	struct ubus_request req;
-	int ret;
+	int ret = UBUS_STATUS_INVALID_ARGUMENT;
+	bool free_ctx = false;
+
+	if (!ctx)
+		free_ctx = (ctx = ubus_connect(NULL)) != NULL;
+	if (!ctx)
+		return -1;
 
 	blob_buf_init(&b, 0);
 	blob_put_int32(&b, UBUS_ATTR_OBJID, obj->id);
 
 	if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_REMOVE_OBJECT, 0) < 0)
-		return UBUS_STATUS_INVALID_ARGUMENT;
+		goto out;
 
 	req.raw_data_cb = ubus_remove_object_cb;
 	req.priv = obj;
 	ret = ubus_complete_request(ctx, &req, 0);
 	if (ret)
-		return ret;
+		goto out;
 
-	if (obj->id)
-		return UBUS_STATUS_NO_DATA;
+	ret = (!obj->id) ? UBUS_STATUS_NO_DATA : 0;
+out:
+	if (free_ctx)
+		ubus_free(ctx);
 
-	return 0;
+	return ret;
 }
diff --git a/libubus-req.c b/libubus-req.c
index 8475dc9..240c2d4 100644
--- a/libubus-req.c
+++ b/libubus-req.c
@@ -225,14 +225,25 @@ int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
 {
 	struct ubus_request req;
 	int rc;
+	bool free_ctx = false;
+
+	if (!ctx)
+		free_ctx = (ctx = ubus_connect(NULL)) != NULL;
+	if (!ctx)
+		return -1;
 
 	rc = ubus_invoke_async(ctx, obj, method, msg, &req);
 	if (rc)
-		return rc;
+		goto out;
 
 	req.data_cb = cb;
 	req.priv = priv;
-	return ubus_complete_request(ctx, &req, timeout);
+	rc = ubus_complete_request(ctx, &req, timeout);
+out:
+	if (free_ctx)
+		ubus_free(ctx);
+
+	return rc;
 }
 
 static void
@@ -288,17 +299,29 @@ int ubus_notify(struct ubus_context *ctx, struct ubus_object *obj,
 {
 	struct ubus_notify_request req;
 	int ret;
+	bool free_ctx = false;
+
+	if (!ctx)
+		free_ctx = (ctx = ubus_connect(NULL)) != NULL;
+	if (!ctx)
+		return -1;
 
 	ret = __ubus_notify_async(ctx, obj, type, msg, &req, timeout >= 0);
 	if (ret < 0)
-		return ret;
+		goto out;
 
 	if (timeout < 0) {
 		ubus_abort_request(ctx, &req.req);
-		return 0;
+		ret = 0;
+		goto out;
 	}
 
-	return ubus_complete_request(ctx, &req.req, timeout);
+	ret = ubus_complete_request(ctx, &req.req, timeout);
+out:
+	if (free_ctx)
+		ubus_free(ctx);
+
+	return ret;
 }
 
 static bool ubus_get_status(struct ubus_msghdr *hdr, int *ret)
diff --git a/libubus-sub.c b/libubus-sub.c
index 8793133..1b51364 100644
--- a/libubus-sub.c
+++ b/libubus-sub.c
@@ -45,16 +45,27 @@ static int
 __ubus_subscribe_request(struct ubus_context *ctx, struct ubus_object *obj, uint32_t id, int type)
 {
 	struct ubus_request req;
+	int ret = UBUS_STATUS_INVALID_ARGUMENT;
+	bool free_ctx = false;
+
+	if (!ctx)
+		free_ctx = (ctx = ubus_connect(NULL)) != NULL;
+	if (!ctx)
+		return -1;
 
 	blob_buf_init(&b, 0);
 	blob_put_int32(&b, UBUS_ATTR_OBJID, obj->id);
 	blob_put_int32(&b, UBUS_ATTR_TARGET, id);
 
 	if (ubus_start_request(ctx, &req, b.head, type, 0) < 0)
-		return UBUS_STATUS_INVALID_ARGUMENT;
+		goto out;
 
-	return ubus_complete_request(ctx, &req, 0);
+	ret = ubus_complete_request(ctx, &req, 0);
+out:
+	if (free_ctx)
+		ubus_free(ctx);
 
+	return ret;
 }
 
 int ubus_subscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id)
diff --git a/libubus.c b/libubus.c
index be4e6ac..27e3d93 100644
--- a/libubus.c
+++ b/libubus.c
@@ -156,18 +156,30 @@ int ubus_lookup(struct ubus_context *ctx, const char *path,
 		ubus_lookup_handler_t cb, void *priv)
 {
 	struct ubus_lookup_request lookup;
+	int ret = UBUS_STATUS_INVALID_ARGUMENT;
+	bool free_ctx = false;
+
+	if (!ctx)
+		free_ctx = (ctx = ubus_connect(NULL)) != NULL;
+	if (!ctx)
+		return -1;
 
 	blob_buf_init(&b, 0);
 	if (path)
 		blob_put_string(&b, UBUS_ATTR_OBJPATH, path);
 
 	if (ubus_start_request(ctx, &lookup.req, b.head, UBUS_MSG_LOOKUP, 0) < 0)
-		return UBUS_STATUS_INVALID_ARGUMENT;
+		goto out;
 
 	lookup.req.raw_data_cb = ubus_lookup_cb;
 	lookup.req.priv = priv;
 	lookup.cb = cb;
-	return ubus_complete_request(ctx, &lookup.req, 0);
+	ret = ubus_complete_request(ctx, &lookup.req, 0);
+out:
+	if (free_ctx)
+		ubus_free(ctx);
+
+	return ret;
 }
 
 static void ubus_lookup_id_cb(struct ubus_request *req, int type, struct blob_attr *msg)
@@ -186,18 +198,30 @@ static void ubus_lookup_id_cb(struct ubus_request *req, int type, struct blob_at
 int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id)
 {
 	struct ubus_request req;
+	int ret = UBUS_STATUS_INVALID_ARGUMENT;
+	bool free_ctx = false;
+
+	if (!ctx)
+		free_ctx = (ctx = ubus_connect(NULL)) != NULL;
+	if (!ctx)
+		return -1;
 
 	blob_buf_init(&b, 0);
 	if (path)
 		blob_put_string(&b, UBUS_ATTR_OBJPATH, path);
 
 	if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_LOOKUP, 0) < 0)
-		return UBUS_STATUS_INVALID_ARGUMENT;
+		goto out;
 
 	req.raw_data_cb = ubus_lookup_id_cb;
 	req.priv = id;
 
-	return ubus_complete_request(ctx, &req, 0);
+	ret = ubus_complete_request(ctx, &req, 0);
+out:
+	if (free_ctx)
+		ubus_free(ctx);
+
+	return ret;
 }
 
 static int ubus_event_cb(struct ubus_context *ctx, struct ubus_object *obj,
@@ -252,6 +276,13 @@ int ubus_send_event(struct ubus_context *ctx, const char *id,
 {
 	struct ubus_request req;
 	void *s;
+	int ret = UBUS_STATUS_INVALID_ARGUMENT;
+	bool free_ctx = false;
+
+	if (!ctx)
+		free_ctx = (ctx = ubus_connect(NULL)) != NULL;
+	if (!ctx)
+		return -1;
 
 	blob_buf_init(&b, 0);
 	blob_put_int32(&b, UBUS_ATTR_OBJID, UBUS_SYSTEM_OBJECT_EVENT);
@@ -262,9 +293,14 @@ int ubus_send_event(struct ubus_context *ctx, const char *id,
 	blob_nest_end(&b, s);
 
 	if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_INVOKE, UBUS_SYSTEM_OBJECT_EVENT) < 0)
-		return UBUS_STATUS_INVALID_ARGUMENT;
+		goto out;
+
+	ret = ubus_complete_request(ctx, &req, 0);
+out:
+	if (free_ctx)
+		ubus_free(ctx);
 
-	return ubus_complete_request(ctx, &req, 0);
+	return ret;
 }
 
 static void ubus_default_connection_lost(struct ubus_context *ctx)
-- 
1.8.4.5
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list