X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=f9b41d2707bd26aff4f95a72aa1885d2f2f09280;hp=fdea20ca4981e942f6c176ae4b6b3ad70aea192f;hb=bc4b3ff16b26d5430fe701fd0680a157c65e21f8;hpb=2288467f63826a06d25ac361fa04ea92ec7ddfa3 diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index fdea20ca4..f9b41d270 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -299,13 +299,41 @@ struct rotation_thread_handle *rotation_thread_handle; struct lttng_ht *agent_apps_ht_by_sock = NULL; /* - * Whether sessiond is ready for commands/notification channel/health check + * The initialization of the session daemon is done in multiple phases. + * + * While all threads are launched near-simultaneously, only some of them + * are needed to ensure the session daemon can start to respond to client * requests. - * NR_LTTNG_SESSIOND_READY must match the number of calls to - * sessiond_notify_ready(). + * + * There are two important guarantees that we wish to offer with respect + * to the initialisation of the session daemon: + * - When the daemonize/background launcher process exits, the sessiond + * is fully able to respond to client requests, + * - Auto-loaded sessions are visible to clients. + * + * In order to achieve this, a number of support threads have to be launched + * to allow the "client" thread to function properly. Moreover, since the + * "load session" thread needs the client thread, we must provide a way + * for the "load session" thread to know that the "client" thread is up + * and running. + * + * Hence, the support threads decrement the lttng_sessiond_ready counter + * while the "client" threads waits for it to reach 0. Once the "client" thread + * unblocks, it posts the message_thread_ready semaphore which allows the + * "load session" thread to progress. + * + * This implies that the "load session" thread is the last to be initialized + * and will explicitly call sessiond_signal_parents(), which signals the parents + * that the session daemon is fully initialized. + * + * The four (4) support threads are: + * - agent_thread + * - notification_thread + * - rotation_thread + * - health_thread */ -#define NR_LTTNG_SESSIOND_READY 6 -int lttng_sessiond_ready = NR_LTTNG_SESSIOND_READY; +#define NR_LTTNG_SESSIOND_SUPPORT_THREADS 4 +int lttng_sessiond_ready = NR_LTTNG_SESSIOND_SUPPORT_THREADS; int sessiond_check_thread_quit_pipe(int fd, uint32_t events) { @@ -314,28 +342,36 @@ int sessiond_check_thread_quit_pipe(int fd, uint32_t events) /* Notify parents that we are ready for cmd and health check */ LTTNG_HIDDEN -void sessiond_notify_ready(void) +void sessiond_signal_parents(void) { - if (uatomic_sub_return(<tng_sessiond_ready, 1) == 0) { - /* - * Notify parent pid that we are ready to accept command - * for client side. This ppid is the one from the - * external process that spawned us. - */ - if (config.sig_parent) { - kill(ppid, SIGUSR1); - } + /* + * Notify parent pid that we are ready to accept command + * for client side. This ppid is the one from the + * external process that spawned us. + */ + if (config.sig_parent) { + kill(ppid, SIGUSR1); + } - /* - * Notify the parent of the fork() process that we are - * ready. - */ - if (config.daemonize || config.background) { - kill(child_ppid, SIGUSR1); - } + /* + * Notify the parent of the fork() process that we are + * ready. + */ + if (config.daemonize || config.background) { + kill(child_ppid, SIGUSR1); } } +LTTNG_HIDDEN +void sessiond_notify_ready(void) +{ + /* + * The _return variant is used since the implied memory barriers are + * required. + */ + (void) uatomic_sub_return(<tng_sessiond_ready, 1); +} + static int __sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size, int *a_pipe) @@ -860,7 +896,7 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd) cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter, socket, node.node) { pthread_mutex_lock(socket->lock); - ret = kernel_consumer_send_channel_stream(socket, + ret = kernel_consumer_send_channel_streams(socket, channel, ksess, session->output_traces ? 1 : 0); pthread_mutex_unlock(socket->lock); @@ -4495,8 +4531,6 @@ static void *thread_manage_clients(void *data) goto error; } - sessiond_notify_ready(); - ret = sem_post(&load_info->message_thread_ready); if (ret) { PERROR("sem_post message_thread_ready"); @@ -4529,6 +4563,7 @@ static void *thread_manage_clients(void *data) if (ret > 0 || (ret < 0 && errno != EINTR)) { goto exit; } + cmm_smp_rmb(); } /* This testpoint is after we signal readiness to the parent. */