dlog_logger: add Dead Reader Storage 01/296201/3
authorMichal Bloch <m.bloch@samsung.com>
Thu, 20 Jul 2023 12:17:26 +0000 (14:17 +0200)
committerMichal Bloch <m.bloch@samsung.com>
Wed, 13 Sep 2023 17:45:11 +0000 (19:45 +0200)
It's there, 'cause storing dead readers is now the server's business, that's why!

Change-Id: I4c546d8e3479b7498c9ed2def85b7f710672b005

src/logger/logger.c
src/logger/logger_internal.c
src/logger/logger_internal.h

index 5728e5c..8d10e3c 100644 (file)
@@ -151,6 +151,42 @@ int add_reader_to_server(struct reader_common *reader, struct logger *server)
        return 0;
 }
 
+__attribute__((noreturn)) static void thread_seppuku(struct reader_common *reader)
+{
+       const pthread_t self = reader->thread;
+       assert(self == pthread_self());
+
+       reader->thread = 0; // make sure the destructor won't join the thread
+       reader_free(reader);
+
+       pthread_detach(self); // since there's nobody to join us
+       pthread_cancel(self);
+       pthread_testcancel(); // force the cancel in case it didn't happen immediately
+       __builtin_unreachable();
+}
+
+void reader_thread_finished(struct reader_common *reader)
+{
+       assert(reader);
+
+       struct logger *const server = reader->server;
+       assert(server);
+
+       int r = pthread_mutex_lock(&server->drs_lock);
+       assert(!r);
+
+       bool ok = list_add(&server->dead_reader_storage, reader);
+
+       r = pthread_mutex_unlock(&server->drs_lock);
+       assert(!r);
+
+       if (ok)
+               return;
+
+       thread_seppuku(reader); // prevent a leak
+       __builtin_unreachable();
+}
+
 int create_fifo_fds(struct logger *server, int pipe_fd[2], int flags, bool dump)
 {
        int ret = get_nonblocking_fifo(pipe_fd, flags);
@@ -469,6 +505,10 @@ int logger_create(struct logger_config_data *data, struct logger *l, struct sign
        if (r < 0)
                return r;
 
+       r = pthread_mutex_init(&l->drs_lock, NULL);
+       if (r < 0)
+               return r;
+
        l->epolltime = data->epoll_time;
        l->sort_by = data->sort_by;
        l->buf_params = data->buf_params;
@@ -565,6 +605,18 @@ int logger_create(struct logger_config_data *data, struct logger *l, struct sign
        return 0;
 }
 
+static void cleanup_dead_readers(struct logger *server)
+{
+       int r = pthread_mutex_lock(&server->drs_lock);
+       assert(!r);
+
+       list_foreach(server->dead_reader_storage, server, reader_free_foreach);
+       list_clear(&server->dead_reader_storage);
+
+       r = pthread_mutex_unlock(&server->drs_lock);
+       assert(!r);
+}
+
 static bool do_logger_one_iteration(struct logger *server, bool *use_lazy_polling)
 {
 
@@ -585,6 +637,7 @@ static bool do_logger_one_iteration(struct logger *server, bool *use_lazy_pollin
                return false;
 
        service_all_readers(server);
+       cleanup_dead_readers(server);
 
        if (server->qos)
                qos_periodic_check(server->qos);
index 705be99..c9bbd7f 100644 (file)
@@ -149,8 +149,11 @@ void logger_free(struct logger *l)
 {
        assert(l);
 
+       (void) pthread_mutex_destroy(&l->drs_lock);
+
        list_foreach(l->writers, l, foreach_writer_free);
        list_foreach(l->readers, l, reader_free_foreach);
+       list_foreach(l->dead_reader_storage, l, reader_free_foreach);
 
        int j;
        for (j = 0; j < LOG_ID_MAX; j++)
index 41add90..2bbba6e 100644 (file)
@@ -157,6 +157,10 @@ struct logger {
        struct qos_module*    qos;
        struct signal_markup* sigmar;
        list_head             compressed_memories;
+
+       /* Dead Reader Storage */
+       list_head             dead_reader_storage;
+       pthread_mutex_t       drs_lock;
 };
 
 struct logger_config_data {
@@ -182,6 +186,7 @@ int create_fifo_fds(struct logger *server, int pipe_fd[2], int flags, bool dump)
 int add_reader_to_server(struct reader_common *reader, struct logger *server);
 void flush_logfile_timely(struct log_file *file, struct timespec ts, int flush_time);
 int get_now(struct now_t *now);
+void reader_thread_finished(struct reader_common *reader);
 
 // these live in `logger_internal.c`, the earlier ones are scattered in various others
 int handle_epoll_events(struct logger *server, struct epoll_metadata *metadata, int timeout);