[LEDE-DEV] [PATCH] ubus cli: wait_for: fix race causing false timeouts

Zefir Kurtisi zefir.kurtisi at neratec.com
Fri Oct 7 04:57:15 PDT 2016


In ubus_cli_wait_for() there is a 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
that 'wait_for' randomly 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. This commit 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>
---

This patch was already posted on the OWRT mailing list like
half a year ago and remained as 'new' in patchwork 
(https://patchwork.ozlabs.org/patch/608750/).

Hoping to get someone looking at it faster than that, this is
a repost with slightly modified commit message.


 cli.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/cli.c b/cli.c
index c5cbfc3..a52d87f 100644
--- a/cli.c
+++ b/cli.c
@@ -22,6 +22,7 @@ static bool simple_output = false;
 static int verbose = 0;
 static int monitor_dir = -1;
 static uint32_t monitor_mask;
+static struct ubus_context *ctx;
 static const char * const monitor_types[] = {
 	[UBUS_MSG_HELLO] = "hello",
 	[UBUS_MSG_STATUS] = "status",
@@ -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




More information about the Lede-dev mailing list