}
/**
+ * @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
{
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;
}
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);
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);
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;
}
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)