dlog_logger daemon: reaching FD limit leaves a log 99/191999/5
authorMichal Bloch <m.bloch@samsung.com>
Fri, 26 Oct 2018 10:31:25 +0000 (12:31 +0200)
committerMichal Bloch <m.bloch@samsung.com>
Mon, 29 Oct 2018 13:44:57 +0000 (14:44 +0100)
Change-Id: Ie70e7fa6e1fe5a3c394e0fd428cf0aa3375e03aa
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
src/logger/logger.c [changed mode: 0755->0644]

old mode 100755 (executable)
new mode 100644 (file)
index a1047c0..df231bd
@@ -757,6 +757,41 @@ static int buffer_append(const struct logger_entry *entry, struct log_buffer *b)
        return 0;
 }
 
+/**
+ * @brief FD limit handler
+ * @details Checks whether the FD limit was reached and leaves logs about it if so
+ * @param[in] server The logger server
+ * @param[in] err errno from the call that failed to create an FD
+ */
+static void check_if_fd_limit_reached(struct logger *server, int err)
+{
+       assert(server);
+
+       if (err != ENFILE && err != EMFILE)
+               return;
+
+       printf("ERROR: dlog_logger fd limit reached!\n");
+
+       /* pick one representative buffer to send the log to;
+        * no point spamming all the buffers, especially since
+        * default dlogutil invocations display 3 buffers so
+        * it would appear multiple times */
+       struct log_buffer *const buf = server->buffers[LOG_ID_MAIN];
+       if (!buf)
+               return;
+
+       struct logger_entry_with_msg entry;
+       create_pipe_message(&entry,
+               DLOG_FATAL, /* not really FATAL, but since we're at the FD limit
+                            * there are thousands of logging programs so this one
+                            * would likely get lost in the flood since developers
+                            * tend to overuse ERROR (and FATAL is the one above) */
+               "DLOG",
+               "\x1b[31m DLOG DAEMON FD LIMIT REACHED \x1b[0m" // make it stand out
+       );
+       buffer_append(&entry.header, buf);
+}
+
 static int reader_print_out_single_log(struct reader *reader, const struct logger_entry *logger_entry)
 {
        assert(reader);
@@ -1021,7 +1056,7 @@ static int reader_init_for_logger(struct reader *reader, const char *buf_name, s
        return 0;
 }
 
-static int create_fifo_fds(int fifo_id, int *write_fd, int *read_fd)
+static int create_fifo_fds(struct logger *server, int fifo_id, int *write_fd, int *read_fd)
 {
        assert(write_fd);
        assert(read_fd);
@@ -1039,12 +1074,14 @@ static int create_fifo_fds(int fifo_id, int *write_fd, int *read_fd)
 
        *read_fd = open(fifo_path, O_RDONLY | O_NONBLOCK);
        if (*read_fd < 0) {
+               check_if_fd_limit_reached(server, errno);
                ret = -errno;
                goto finish;
        }
 
        *write_fd = open(fifo_path, O_WRONLY | O_NONBLOCK);
        if (*write_fd < 0) {
+               check_if_fd_limit_reached(server, errno);
                ret = -errno;
                close(*read_fd);
                goto finish;
@@ -1183,7 +1220,7 @@ 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(wr->fd_entity.fd, &write_fd, &read_fd) < 0)
+               if (create_fifo_fds(server, wr->fd_entity.fd, &write_fd, &read_fd) < 0)
                        goto cleanup;
 
                set_write_fd_entity(&reader->fd_entity, write_fd);
@@ -1354,8 +1391,10 @@ static int service_writer_handle_req_pipe(struct logger* server, struct writer*
                return -EINVAL;
 
        int pipe_fd[2];
-       if (pipe2(pipe_fd, O_CLOEXEC | O_NONBLOCK) < 0) // O_NONBLOCK just for pipe_fd[0]; writer removes it for pipe_fd[1] on its own
+       if (pipe2(pipe_fd, O_CLOEXEC | O_NONBLOCK) < 0) { // O_NONBLOCK just for pipe_fd[0]; writer removes it for pipe_fd[1] on its own
+               check_if_fd_limit_reached(server, errno);
                return -errno;
+       }
 
        r = fcntl(pipe_fd[1], F_SETPIPE_SZ, PIPE_REQUESTED_SIZE);
        if (r < 0)
@@ -1767,8 +1806,10 @@ static void dispatch_event_sock(struct logger *server, struct epoll_event *event
 
        assert(sock);
        int sock_pipe = accept4(sock->fd_entity.fd, NULL, NULL, SOCK_NONBLOCK);
-       if (sock_pipe < 0)
+       if (sock_pipe < 0) {
+               check_if_fd_limit_reached(server, errno);
                return;
+       }
 
        struct writer *writer;
        if (writer_create(&writer, sock_pipe, sock->buf_ptr, service_writer_socket, sock->service_socket) == 0)