[LEDE-DEV] [PATCH] ubox logread

Maksym Ruchko MRuchko at advantech-bb.com
Thu Oct 19 08:57:12 PDT 2017


The read optimization with buffer ustream in the logread caused the logger to hung randomly, more often under high load and when logged messages are large.

To reproduce 100% compile and run:
#include <syslog.h>
#include <stdlib.h>
#include <string.h>

#define BUF_SIZE 8192

int i;
static char msg_buf[BUF_SIZE];

int main(int argc, char* argv[])
{
        setlogmask(LOG_UPTO(LOG_NOTICE));

        openlog(argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);

        syslog(LOG_NOTICE, "Program started by User %d", getuid());
        syslog(LOG_INFO, "A tree falls in a forest");

        memset(msg_buf, 'A', BUF_SIZE - 1);
        msg_buf[BUF_SIZE-1] = '\0';
        for (i=0; i < 10; ++i) syslog(LOG_NOTICE, msg_buf);

        syslog(LOG_NOTICE, "After");

        closelog();

        exit(0);
}

The line "After" will not show up in the log and all subsequent log messages are blocked.

Patch below against ubox master branch at https://git.openwrt.org/project/ubox.git  fixes the problem, keeping buffers trickery as fast patch for short messages.


--- log/logread.c.orig  2017-10-19 16:31:04.033719240 +0100
+++ log/logread.c       2017-10-19 16:44:49.203118281 +0100
@@ -223,18 +223,34 @@
 {
        while (true) {
                struct blob_attr *a;
-               int len, cur_len;
+               int len, full_blob_len, read_pending_len, read;
+               char* buf;
 
                a = (void*) ustream_get_read_buf(s, &len);
                if (len < sizeof(*a))
                        break;
 
-               cur_len = blob_len(a) + sizeof(*a);
-               if (len < cur_len)
-                       break;
-
-               log_notify(a);
-               ustream_consume(s, cur_len);
+               full_blob_len = blob_raw_len(a);
+               if (len < full_blob_len) {
+                       read_pending_len = ustream_pending_data(s, false);
+                       if (read_pending_len < full_blob_len)
+                               break;
+                       buf = malloc(full_blob_len);
+                       if (buf) {
+                               read = 0;
+                               do {
+                                       read += ustream_read(s, buf + read, full_blob_len - read);
+                               } while (read < full_blob_len);
+                               log_notify((struct blob_attr*)buf);
+                               free(buf);
+                       } else {
+                               fprintf(stderr, "Malloc failed\n");
+                               break;
+                       }
+               } else {
+                       log_notify(a);
+                       ustream_consume(s, full_blob_len);
+               }
        }
        if (!log_follow)
                uloop_end();
@@ -245,6 +261,7 @@
        static struct ustream_fd test_fd;
 
        test_fd.stream.notify_read = logread_fd_data_cb;
+       test_fd.stream.r.max_buffers = -1;
        ustream_fd_init(&test_fd, fd);
 }


Maksym Ruchko
mruchko at advantech-bb.com



More information about the Lede-dev mailing list