[LEDE-DEV] [PATCH v2] ubox/logread: add re-connect capability

John Crispin john at phrozen.org
Wed Feb 14 00:31:05 PST 2018



On 24/11/17 14:06, Zefir Kurtisi wrote:
> When logd is restarted while 'logread -f' is running, the
> logread process terminates, which cumbers debugging in
> different use-cases.
>
> This patch adds re-connect functionality to logread. In
> follow mode, when the ustream to logd is disconnected,
> instead of terminating, it tries to re-connect to logd
> and re-issue the original request.
>
> Signed-off-by: Zefir Kurtisi <zefir.kurtisi at neratec.com>

Hi Zefir,

I have just pushed a different version of the patch, thanks for 
reporting the problem

     John

> ---
> v2: in follow mode, don't exit if the initial
>      ubus lookup for logd fails
>
>   log/logread.c | 143 +++++++++++++++++++++++++++++++++++++---------------------
>   1 file changed, 91 insertions(+), 52 deletions(-)
>
> diff --git a/log/logread.c b/log/logread.c
> index ad06f2a..8229c98 100644
> --- a/log/logread.c
> +++ b/log/logread.c
> @@ -65,6 +65,10 @@ static int log_type = LOG_STDOUT;
>   static int log_size, log_udp, log_follow, log_trailer_null = 0;
>   static int log_timestamp;
>   static int last_errno = 0;
> +static struct ubus_context *ctx;
> +static int lines;
> +
> +static void logread_reconnect_cb(struct uloop_timeout *timeout);
>   
>   static const char* getcodetext(int value, CODE *codetable) {
>   	CODE *i;
> @@ -268,29 +272,82 @@ static void logread_fd_data_cb(struct ustream *s, int bytes)
>   	}
>   }
>   
> +/*
> + * Reconnect Handling
> + * while following log
> + * - after logd removal
> + *   - destroy ustream
> + *   - cyclically try to re-connect to new logd object
> + *   - re-issue original request
> + *
> + * Note: if a re-connection appears while a 'logread -l' request is active, the
> + *       number of returned lines will not match (i.e. you get some lines from
> + *       the old instance plus the number of lines requested from the new one)
> + */
> +
> +/* flag to prevent printing error messages during reconnect cycles */
> +static int object_reconnect_active;
> +
> +static void logread_restart_reconnect_timer(struct uloop_timeout *timeout)
> +{
> +	const int LOG_RECONNECT_TIMEOUT_MS = 250;
> +	uloop_timeout_set(timeout, LOG_RECONNECT_TIMEOUT_MS);
> +}
> +
>   static void logread_fd_state_cb(struct ustream *s)
>   {
> -	uloop_end();
> +	static struct uloop_timeout ubus_timer;
> +	/* force re-opening of stream */
> +	s->free(s);
> +
> +	object_reconnect_active = 1;
> +	ubus_timer.cb = logread_reconnect_cb;
> +	logread_restart_reconnect_timer(&ubus_timer);
>   }
>   
>   static void logread_fd_cb(struct ubus_request *req, int fd)
>   {
>   	static struct ustream_fd test_fd;
> -
>   	test_fd.stream.notify_read = logread_fd_data_cb;
>   	test_fd.stream.notify_state = logread_fd_state_cb;
>   	ustream_fd_init(&test_fd, fd);
>   }
>   
> -int main(int argc, char **argv)
> +static int logread_process(void)
>   {
> +	static struct blob_buf b;
>   	static struct ubus_request req;
> -	struct ubus_context *ctx;
>   	uint32_t id;
> +	int ret = ubus_lookup_id(ctx, "log", &id);
> +	if (ret) {
> +		if (!object_reconnect_active)
> +			fprintf(stderr, "Failed to find log object\n");
> +		return ret;
> +	}
> +	blob_buf_init(&b, 0);
> +	blobmsg_add_u8(&b, "stream", 1);
> +	if (lines)
> +		blobmsg_add_u32(&b, "lines", lines);
> +	else if (log_follow)
> +		blobmsg_add_u32(&b, "lines", 0);
> +
> +	ubus_invoke_async(ctx, id, "read", b.head, &req);
> +	req.fd_cb = logread_fd_cb;
> +	ubus_complete_request_async(ctx, &req);
> +
> +	return 0;
> +}
> +
> +static void logread_reconnect_cb(struct uloop_timeout *timeout)
> +{
> +	if (logread_process())
> +		logread_restart_reconnect_timer(timeout);
> +}
> +
> +int main(int argc, char **argv)
> +{
>   	const char *ubus_socket = NULL;
> -	int ch, ret, lines = 0;
> -	static struct blob_buf b;
> -	int tries = 5;
> +	int ch, ret;
>   
>   	signal(SIGPIPE, SIG_IGN);
>   
> @@ -354,58 +411,40 @@ int main(int argc, char **argv)
>   	}
>   	ubus_add_uloop(ctx);
>   
> -	/* ugly ugly ugly ... we need a real reconnect logic */
> -	do {
> -		ret = ubus_lookup_id(ctx, "log", &id);
> -		if (ret) {
> -			fprintf(stderr, "Failed to find log object: %s\n", ubus_strerror(ret));
> -			sleep(1);
> -			continue;
> -		}
> -
> -		blob_buf_init(&b, 0);
> -		blobmsg_add_u8(&b, "stream", 1);
> -		blobmsg_add_u8(&b, "oneshot", !log_follow);
> -		if (lines)
> -			blobmsg_add_u32(&b, "lines", lines);
> -		else if (log_follow)
> -			blobmsg_add_u32(&b, "lines", 0);
> -		if (log_follow) {
> -			if (pid_file) {
> -				FILE *fp = fopen(pid_file, "w+");
> -				if (fp) {
> -					fprintf(fp, "%d", getpid());
> -					fclose(fp);
> -				}
> +	if (log_follow) {
> +		if (pid_file) {
> +			FILE *fp = fopen(pid_file, "w+");
> +			if (fp) {
> +				fprintf(fp, "%d", getpid());
> +				fclose(fp);
>   			}
>   		}
> +	}
>   
> -		if (log_ip && log_port) {
> -			openlog("logread", LOG_PID, LOG_DAEMON);
> -			log_type = LOG_NET;
> -			sender.cb = log_handle_fd;
> -			retry.cb = log_handle_reconnect;
> -			uloop_timeout_set(&retry, 1000);
> -		} else if (log_file) {
> -			log_type = LOG_FILE;
> -			sender.fd = open(log_file, O_CREAT | O_WRONLY| O_APPEND, 0600);
> -			if (sender.fd < 0) {
> -				fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
> -				exit(-1);
> -			}
> -		} else {
> -			sender.fd = STDOUT_FILENO;
> +	if (log_ip && log_port) {
> +		openlog("logread", LOG_PID, LOG_DAEMON);
> +		log_type = LOG_NET;
> +		sender.cb = log_handle_fd;
> +		retry.cb = log_handle_reconnect;
> +		uloop_timeout_set(&retry, 1000);
> +	} else if (log_file) {
> +		log_type = LOG_FILE;
> +		sender.fd = open(log_file, O_CREAT | O_WRONLY| O_APPEND, 0600);
> +		if (sender.fd < 0) {
> +			fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
> +			exit(-1);
>   		}
> +	} else {
> +		sender.fd = STDOUT_FILENO;
> +	}
>   
> -		ubus_invoke_async(ctx, id, "read", b.head, &req);
> -		req.fd_cb = logread_fd_cb;
> -		ubus_complete_request_async(ctx, &req);
> -
> +	ret = logread_process();
> +	/* unless we are following, immediately exit when logd is not up */
> +	if (!ret || log_follow)
>   		uloop_run();
> -		ubus_free(ctx);
> -		uloop_done();
>   
> -	} while (ret && tries--);
> +	ubus_free(ctx);
> +	uloop_done();
>   
>   	return ret;
>   }




More information about the Lede-dev mailing list