X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=489cc9d7646e5643634e04d27e71057beceee930;hp=532e345c08ded85521bce34437d911d58e6156ab;hb=d086f507d02078aed618ab291a0bc4a634958fa3;hpb=62c43103c60bd704cd8ed7acaaa22465802f5673 diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 532e345c0..489cc9d76 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -73,10 +73,12 @@ #include "load-session-thread.h" #include "notification-thread.h" #include "notification-thread-commands.h" +#include "rotation-thread.h" #include "syscall.h" #include "agent.h" #include "ht-cleanup.h" #include "sessiond-config.h" +#include "sessiond-timer.h" static const char *help_msg = #ifdef LTTNG_EMBED_HELP @@ -208,6 +210,8 @@ static pthread_t ht_cleanup_thread; static pthread_t agent_reg_thread; static pthread_t load_session_thread; static pthread_t notification_thread; +static pthread_t rotation_thread; +static pthread_t timer_thread; /* * UST registration command queue. This queue is tied with a futex and uses a N @@ -288,6 +292,9 @@ struct load_session_thread_data *load_info; /* Notification thread handle. */ struct notification_thread_handle *notification_thread_handle; +/* Rotation thread handle. */ +struct rotation_thread_handle *rotation_thread_handle; + /* Global hash tables */ struct lttng_ht *agent_apps_ht_by_sock = NULL; @@ -297,7 +304,7 @@ struct lttng_ht *agent_apps_ht_by_sock = NULL; * NR_LTTNG_SESSIOND_READY must match the number of calls to * sessiond_notify_ready(). */ -#define NR_LTTNG_SESSIOND_READY 4 +#define NR_LTTNG_SESSIOND_READY 5 int lttng_sessiond_ready = NR_LTTNG_SESSIOND_READY; int sessiond_check_thread_quit_pipe(int fd, uint32_t events) @@ -5464,6 +5471,48 @@ end: return ret; } +static +struct rotation_thread_timer_queue *create_rotate_timer_queue(void) +{ + struct rotation_thread_timer_queue *queue = NULL; + + queue = zmalloc(sizeof(struct rotation_thread_timer_queue)); + if (!queue) { + PERROR("Failed to allocate timer rotate queue"); + goto end; + } + + queue->event_pipe = lttng_pipe_open(FD_CLOEXEC | O_NONBLOCK); + CDS_INIT_LIST_HEAD(&queue->list); + pthread_mutex_init(&queue->lock, NULL); + +end: + return queue; +} + +static +void destroy_rotate_timer_queue(struct rotation_thread_timer_queue *queue) +{ + struct sessiond_rotation_timer *node, *tmp_node; + + if (!queue) { + return; + } + + lttng_pipe_destroy(queue->event_pipe); + + pthread_mutex_lock(&queue->lock); + /* Empty wait queue. */ + cds_list_for_each_entry_safe(node, tmp_node, &queue->list, head) { + cds_list_del(&node->head); + free(node); + } + pthread_mutex_unlock(&queue->lock); + + pthread_mutex_destroy(&queue->lock); + free(queue); +} + /* * main */ @@ -5476,9 +5525,14 @@ int main(int argc, char **argv) *ust64_channel_monitor_pipe = NULL, *kernel_channel_monitor_pipe = NULL; bool notification_thread_running = false; + bool rotation_thread_running = false; + bool timer_thread_running = false; struct lttng_pipe *ust32_channel_rotate_pipe = NULL, *ust64_channel_rotate_pipe = NULL, *kernel_channel_rotate_pipe = NULL; + struct timer_thread_parameters timer_thread_ctx; + /* Queue of rotation jobs populated by the sessiond-timer. */ + struct rotation_thread_timer_queue *rotation_timer_queue = NULL; init_kernel_workarounds(); @@ -5489,6 +5543,11 @@ int main(int argc, char **argv) goto exit_set_signal_handler; } + if (sessiond_timer_signal_init()) { + retval = -1; + goto exit_set_signal_handler; + } + page_size = sysconf(_SC_PAGESIZE); if (page_size < 0) { PERROR("sysconf _SC_PAGESIZE"); @@ -5676,6 +5735,17 @@ int main(int argc, char **argv) goto exit_init_data; } + /* + * The rotation_timer_queue structure is shared between the sessiond timer + * thread and the rotation thread. The main() keeps the ownership and + * destroys it when both threads have quit. + */ + rotation_timer_queue = create_rotate_timer_queue(); + if (!rotation_timer_queue) { + retval = -1; + goto exit_init_data; + } + timer_thread_ctx.rotation_timer_queue = rotation_timer_queue; ust64_channel_monitor_pipe = lttng_pipe_open(0); if (!ust64_channel_monitor_pipe) { @@ -5894,6 +5964,44 @@ int main(int argc, char **argv) } notification_thread_running = true; + /* Create timer thread. */ + ret = pthread_create(&timer_thread, default_pthread_attr(), + sessiond_timer_thread, &timer_thread_ctx); + if (ret) { + errno = ret; + PERROR("pthread_create timer"); + retval = -1; + stop_threads(); + goto exit_notification; + } + timer_thread_running = true; + + /* rotation_thread_data acquires the pipes' read side. */ + rotation_thread_handle = rotation_thread_handle_create( + ust32_channel_rotate_pipe, + ust64_channel_rotate_pipe, + kernel_channel_rotate_pipe, + thread_quit_pipe[0], + rotation_timer_queue); + if (!rotation_thread_handle) { + retval = -1; + ERR("Failed to create rotation thread shared data"); + stop_threads(); + goto exit_rotation; + } + + /* Create rotation thread. */ + ret = pthread_create(&rotation_thread, default_pthread_attr(), + thread_rotation, rotation_thread_handle); + if (ret) { + errno = ret; + PERROR("pthread_create rotation"); + retval = -1; + stop_threads(); + goto exit_rotation; + } + rotation_thread_running = true; + /* Create thread to manage the client socket */ ret = pthread_create(&client_thread, default_pthread_attr(), thread_manage_clients, (void *) NULL); @@ -6060,6 +6168,7 @@ exit_dispatch: } exit_client: +exit_rotation: exit_notification: ret = pthread_join(health_thread, &status); if (ret) { @@ -6109,6 +6218,34 @@ exit_init_data: notification_thread_handle_destroy(notification_thread_handle); } + if (rotation_thread_handle) { + if (rotation_thread_running) { + ret = pthread_join(rotation_thread, &status); + if (ret) { + errno = ret; + PERROR("pthread_join rotation thread"); + retval = -1; + } + } + rotation_thread_handle_destroy(rotation_thread_handle); + } + + if (timer_thread_running) { + kill(getpid(), LTTNG_SESSIOND_SIG_EXIT); + ret = pthread_join(timer_thread, &status); + if (ret) { + errno = ret; + PERROR("pthread_join timer thread"); + retval = -1; + } + } + + /* + * After the rotation and timer thread have quit, we can safely destroy + * the rotation_timer_queue. + */ + destroy_rotate_timer_queue(rotation_timer_queue); + rcu_thread_offline(); rcu_unregister_thread();