[OpenWrt-Devel] [PATCH] ubus: cli.wait_for: add polling for services

Zefir Kurtisi zefir.kurtisi at neratec.com
Mon Apr 11 07:18:37 EDT 2016


In ubus_cli_wait_for() there is a potential critical section
between initially checking for the requested services and
the following handling of 'ubus.object.add' events.

In our system we let procd (re)start services and synchronize
inter-service dependencies by using 'ubus wait_for' in the
initscripts' service_started() functions. There we observe
randomly that 'wait_for' is waiting for the full timeout
and returning UBUS_STATUS_TIMEOUT, even if the service it
is waiting for is already up and running.

This happens when the service is started in the critical
section mentioned above.

The proposed patch adds periodic lookup for the requested
services while waiting for the 'add' event and with that
fixes the observed failure.

Signed-off-by: Zefir Kurtisi <zefir.kurtisi at neratec.com>
---
 cli.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/cli.c b/cli.c
index c5cbfc3..8d98b12 100644
--- a/cli.c
+++ b/cli.c
@@ -16,6 +16,7 @@
 #include <libubox/blobmsg_json.h>
 #include "libubus.h"
 
+static struct ubus_context *ctx;
 static struct blob_buf b;
 static int timeout = 30;
 static bool simple_output = false;
@@ -277,15 +278,27 @@ static void wait_timeout(struct uloop_timeout *timeout)
 	uloop_end();
 }
 
-static int ubus_cli_wait_for(struct ubus_context *ctx, int argc, char **argv)
-{
-	struct cli_wait_data data = {
+#define WAIT_LOOP_TIME 200
+static struct cli_wait_data data = {
 		.timeout.cb = wait_timeout,
 		.ev.cb = wait_event_cb,
-		.pending = argv,
-		.n_pending = argc,
-	};
+};
+
+static void poll_timeout_cb(struct uloop_timeout *timeout)
+{
+	int ret = ubus_lookup(ctx, NULL, wait_list_cb, &data);
+	if (ret || !data.n_pending) {
+		uloop_end();
+		return;
+	}
+	uloop_timeout_set(timeout, WAIT_LOOP_TIME);
+}
+static int ubus_cli_wait_for(struct ubus_context *ctx, int argc, char **argv)
+{
+	data.pending = argv;
+	data.n_pending = argc;
 	int ret;
+	static struct uloop_timeout poll_timeout = { .cb = poll_timeout_cb, };
 
 	if (argc < 1)
 		return -2;
@@ -305,6 +318,7 @@ static int ubus_cli_wait_for(struct ubus_context *ctx, int argc, char **argv)
 		return ret;
 
 	uloop_timeout_set(&data.timeout, timeout * 1000);
+	uloop_timeout_set(&poll_timeout, WAIT_LOOP_TIME);
 	uloop_run();
 	uloop_done();
 
@@ -509,7 +523,6 @@ static struct {
 int main(int argc, char **argv)
 {
 	const char *progname, *ubus_socket = NULL;
-	struct ubus_context *ctx;
 	char *cmd;
 	int ret = 0;
 	int i, ch;
-- 
2.7.4
_______________________________________________
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