dlog_logger: improve reader epoll registration 29/192129/4 accepted/tizen/5.0/unified/20181113.090059 accepted/tizen/unified/20181113.085958 submit/tizen/20181112.002448 submit/tizen_5.0/20181112.002456
authorMichal Bloch <m.bloch@samsung.com>
Mon, 29 Oct 2018 16:54:28 +0000 (17:54 +0100)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Thu, 1 Nov 2018 01:27:59 +0000 (01:27 +0000)
 * now keeps readers registered with EPOLLHUP for
   immediate removal when the other end gets closed

 * no longer attempts to unregister already unregistered FDs

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

index df231bd..82cda46 100644 (file)
@@ -415,6 +415,29 @@ static inline int add_fd_entity(struct logger *logger, struct fd_entity *fd_enti
 }
 
 /**
+ * @brief Modify given FD entity to logger event notification
+ * @details Uses epoll mechanism for notification of events
+ * @param[in] logger server owning epoll main loop
+ * @param[in] fd_entity file descriptor entity
+ * @param[in] wanted_mask wanted event mask
+ * @return 0 on success, -errno on failure
+ */
+static inline int modify_fd_entity(const struct logger *logger, struct fd_entity *fd_entity, int wanted_mask)
+{
+       assert(logger);
+       assert(fd_entity);
+
+       if (fd_entity->fd < 0)
+               return -EINVAL;
+
+       if (fd_entity->event.events == wanted_mask)
+               return 0;
+       fd_entity->event.events = wanted_mask;
+
+       return epoll_ctl(logger->epollfd, EPOLL_CTL_MOD, fd_entity->fd, &fd_entity->event) < 0 ? -errno : 0;
+}
+
+/**
  * @brief Remove given FD entity from logger event notification
  * @details Uses epoll mechanism for notification of events
  * @param[in] logger server owning epoll main loop
@@ -479,7 +502,11 @@ static void set_write_fd_entity(struct fd_entity *fd_entity, int fd)
 {
        assert(fd_entity);
        assert(fd >= 0);
-       fd_entity->event.events = EPOLLOUT;
+
+       fd_entity->event.events = EPOLLHUP; /* not EPOLLOUT - readers start dormant,
+                                            * get written to in atomic-like chunks,
+                                            * and only temporarily use EPOLLOUT if
+                                            * their pipe gets clogged mid-chunk */
        fd_entity->fd = fd;
 }
 
@@ -1003,6 +1030,10 @@ static int add_reader(struct logger *server, struct reader *reader)
        assert(reader);
        assert(server);
 
+       int r = add_fd_entity(server, &reader->fd_entity);
+       if (r < 0)
+               return r;
+
        if (reader->buf_ptr)
                return add_buffer_reader(reader->buf_ptr, reader);
 
@@ -1220,7 +1251,8 @@ static int parse_command_line(const char *cmdl, struct writer *wr, struct logger
                        goto cleanup;
        } else if (wr) {
                int write_fd = -1, read_fd = -1;
-               if (create_fifo_fds(server, wr->fd_entity.fd, &write_fd, &read_fd) < 0)
+               retval = create_fifo_fds(server, wr->fd_entity.fd, &write_fd, &read_fd);
+               if (retval < 0)
                        goto cleanup;
 
                set_write_fd_entity(&reader->fd_entity, write_fd);
@@ -1567,21 +1599,17 @@ static int cond_service_reader(void *ptr, void *user_data)
        if (!logger->exiting && reader_should_buffer(reader, &logger->buf_params))
                return FALSE;
 
-       //remove reader from epoll loop and handle it by itself
-       if (reader->fd_entity.fd >= 0)
-               remove_fd_entity(logger, &reader->fd_entity);
-
        assert(reader->service_reader);
        int r = reader->service_reader(reader);
 
-       //when reader still waits for its resouce add it again to epoll loop
-       if (r == 0 && reader->fd_entity.fd >= 0)
-               add_fd_entity(logger, &reader->fd_entity);
-
        if (r > 0) {
+               if (reader->fd_entity.fd >= 0)
+                       remove_fd_entity(logger, &reader->fd_entity);
                reader_free(reader);
                return TRUE;
        }
+
+       modify_fd_entity(logger, &reader->fd_entity, (r == 0) ? EPOLLOUT : EPOLLHUP);
        return FALSE;
 }
 
@@ -1597,6 +1625,14 @@ static void dispatch_event_reader(struct logger *server, struct epoll_event *eve
        struct reader *reader = (struct reader *)event->data.ptr;
 
        assert(reader);
+
+       if (event->events & (EPOLLHUP | EPOLLERR)) {
+               list_remove(&reader->buf_ptr->readers, reader);
+               remove_fd_entity(server, &reader->fd_entity);
+               reader_free(reader);
+               return;
+       }
+
        assert(reader->service_reader);
        int r = reader->service_reader(reader);
        if (r != 0)