util: fix premature exit in dump mode 01/171201/1
authorMichal Bloch <m.bloch@samsung.com>
Tue, 27 Feb 2018 09:43:21 +0000 (10:43 +0100)
committerMichal Bloch <m.bloch@samsung.com>
Tue, 27 Feb 2018 10:51:14 +0000 (11:51 +0100)
The program would end when epoll reported no ready file descriptors.
This was incorrect as data could still be awaiting to be put into
the fd when dlogutil read data from a pipe faster than dlog_logger
could feed it. Android Logger relied on this behaviour to exit when
there were no logs to read as there would not be a read() to trigger
the exit through its regular "log_len quota filled" exit path, but is
otherwise unaffected.

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

index 2f2282e..b4a3962 100755 (executable)
@@ -107,7 +107,7 @@ static void do_print(struct fd_info **data_fds, int fd_count, int dump, struct s
        int nfds;
        int r;
        struct fd_info *fdi = NULL;
-       int pipes = 0;
+       int epoll_cnt = 0;
 
        int epollfd;
        struct epoll_event ev = { .events = EPOLLIN };
@@ -119,17 +119,21 @@ static void do_print(struct fd_info **data_fds, int fd_count, int dump, struct s
                ev.data.ptr = data_fds[nfds];
                if (fd_set_flags(fd, O_NONBLOCK) < 0)
                        return;
-               if (data_fds[nfds]->ops == &ops_pipe) // HACK
-                       ++pipes;
                if (data_fds[nfds]->ops != &ops_binfile) { // HACK
-                       epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
+                       if (data_fds[nfds]->log_len != 0) {
+                               /* can't rely on the regular log_len-based removal path
+                                  as there would potentially be no read to trigger it */
+                               epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
+                               ++epoll_cnt;
+                       }
+
                        struct fd_info *swap_tmp = data_fds[nfds];
                        data_fds[nfds--] = data_fds[--fd_count];
                        data_fds[fd_count] = swap_tmp; // swap non-destructively lest memory leak
                }
        }
 
-       while (true) {
+       while ((epoll_cnt + fd_count) > 0) {
                if (!fdi && !dump)
                        flush_logs(logs, l_file);
 
@@ -138,8 +142,6 @@ static void do_print(struct fd_info **data_fds, int fd_count, int dump, struct s
                        fdi = (struct fd_info*) ev.data.ptr;
                else if (nfds == 0 && fd_count > 0)
                        fdi = data_fds[fd_count - 1];
-               else if (dump)
-                       break;
                else {
                        fdi = NULL;
                        continue;
@@ -158,13 +160,11 @@ static void do_print(struct fd_info **data_fds, int fd_count, int dump, struct s
                                break;
 
                if (r == 0 || (dump && fdi->log_len <= 0 && fdi->log_len != UNLIMITED_LOG_LEN)) {
-                       if (fdi->ops != &ops_binfile) // HACK
+                       if (fdi->ops != &ops_binfile) // HACK
                                epoll_ctl(epollfd, EPOLL_CTL_DEL, fdi->fd, NULL);
-
-                       if (fdi->ops == &ops_pipe && dump) // HACK
-                               --pipes;
-                       else if (--fd_count <= 0)
-                               break;
+                               --epoll_cnt;
+                       } else
+                               --fd_count;
                }
        }