[LEDE-DEV] [PATCH] ubox/logread: add re-connect capability
Zefir Kurtisi
zefir.kurtisi at neratec.com
Tue Nov 21 08:27:53 PST 2017
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>
---
log/logread.c | 142 +++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 90 insertions(+), 52 deletions(-)
diff --git a/log/logread.c b/log/logread.c
index 784d1f9..99f9948 100644
--- a/log/logread.c
+++ b/log/logread.c
@@ -63,6 +63,10 @@ static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostna
static int log_type = LOG_STDOUT;
static int log_size, log_udp, log_follow, log_trailer_null = 0;
static int log_timestamp;
+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;
@@ -236,29 +240,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);
@@ -322,58 +379,39 @@ 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();
+ if (!ret)
uloop_run();
- ubus_free(ctx);
- uloop_done();
- } while (ret && tries--);
+ ubus_free(ctx);
+ uloop_done();
return ret;
}
--
2.14.1
More information about the Lede-dev
mailing list