Fix dlogutil -d under Android Logger backend 59/127759/3
authorMichal Bloch <m.bloch@samsung.com>
Fri, 28 Apr 2017 13:12:35 +0000 (15:12 +0200)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Tue, 16 May 2017 11:37:11 +0000 (13:37 +0200)
Util would keep reading as long as any data was in the buffer,
so if data came faster than it was processed then it would be
working indefinitely.

Now, it learns how many logs are present right at the start
by sending a get length request and only reads that many.

Change-Id: Idcfc7b10776ff93c85f16b335dad36d12bf5cd8e
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
src/logutil/logutil.c

index 4cd0d5a..516f764 100644 (file)
@@ -62,6 +62,8 @@
 
 #define DEFAULT_SORT_TIMEOUT 1000 // ms
 
+#define UNLIMITED_LOG_LEN 0
+
 static int sort_buffer_size = 0;
 static long sort_timeout = DEFAULT_SORT_TIMEOUT;
 static struct log_file l_file;
@@ -87,6 +89,7 @@ typedef enum {
 struct fd_info {
        int fd;
        int do_sorting;
+       int log_len;
        fd_type type;
        int index;
        char buff[RECEIVE_BUFFER_SIZE];
@@ -188,6 +191,23 @@ static int do_clear_pipe(int sock_fd)
        free(msg);
        return ret;
 }
+/**
+ * @brief Get buffer filled size
+ * @details Sends a get log len ioctl to given fd
+ * @param[in] fd File descriptor of the buffer
+ * @return -errno on failure, else >= 0 length in bytes
+ * @remarks ANDROID LOGGER version
+ */
+int logger_get_log_len(int fd)
+{
+       int ret = ioctl(fd, LOGGER_GET_LOG_LEN);
+       if (ret < 0) {
+               const int saved_errno = errno;
+               _E("ioctl LOGGER_GET_LOG_LEN failed (%d)", saved_errno);
+               return -saved_errno;
+       }
+       return ret;
+}
 
 /**
  * @brief Clear the buffer
@@ -400,18 +420,30 @@ static void handle_pipe(struct fd_info **data_fds, int fd_count, int dump)
                        }
                }
 
-               if (r == 0) {
+               int stop = (r == 0);
+               if (dump && !stop && fdi->log_len > 0) {
+                       fdi->log_len -= r;
+                       if (fdi->log_len <= 0)
+                               stop = 1;
+               }
+
+               filled = 1;
+               fdi->index += r;
+
+               if (stop) {
+                       if (fdi->type != BINARY_FILE)
+                               epoll_ctl(epollfd, EPOLL_CTL_DEL, fdi->fd, NULL);
+
                        if (fdi->type == PIPE && dump) {
                                --pipes;
-                               epoll_ctl(epollfd, EPOLL_CTL_DEL, fdi->fd, NULL);
                        } else if (--fd_count <= 0)
                                accepting_logs = 0;
-                       continue;
+                       if (r == 0)
+                               continue;
+                       else
+                               filled = 0;
                }
 
-               filled = 1;
-               fdi->index += r;
-
                e = (struct logger_entry *)fdi->buff;
                switch (fdi->type) {
                case ANDROID_LOGGER: {
@@ -503,6 +535,7 @@ struct fd_info * handle_file(char const * filename)
                goto closefile;
        fdi->fd = fd;
        fdi->do_sorting = 1;
+       fdi->log_len = UNLIMITED_LOG_LEN;
        fdi->type = BINARY_FILE;
        fdi->index = 0;
        return fdi;
@@ -556,12 +589,17 @@ struct fd_info * process_buffer_nonpipe(char * buffer_name, int clear, struct lo
                goto cleanup;
        }
 
+       const int log_len = logger_get_log_len(fd);
+       if (log_len < 0)
+               goto cleanup;
+
        struct fd_info * fdi = malloc(sizeof(struct fd_info));
        if (!fdi)
                goto cleanup;
        fdi->fd = fd;
        fdi->do_sorting = 1;
        fdi->type = ANDROID_LOGGER;
+       fdi->log_len = log_len;
        fdi->index = 0;
        return fdi;
 
@@ -636,6 +674,7 @@ struct fd_info * process_buffer_pipe(char * buffer_name, int clear, struct log_c
                goto cleanup;
        }
        ret->fd = pipe_fd;
+       ret->log_len = UNLIMITED_LOG_LEN;
        ret->do_sorting = strncmp(buffer_name, "kmsg", 5) && strncmp(buffer_name, "syslog", 7);
        ret->type = PIPE;