X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=9cde946495436f04590339475e96f95b5ea7421c;hp=0c97b1cb64fe196370fae53634e7c65246f53729;hb=b35308203f7844f48542978fd00aab21f2057c17;hpb=22dad56815ce0201c5ae7d5ef5d79cc0c6a42c5e diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 0c97b1cb6..9cde94649 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -70,13 +71,16 @@ #include "agent-thread.h" #include "save.h" #include "load-session-thread.h" +#include "notification-thread.h" +#include "notification-thread-commands.h" #include "syscall.h" #include "agent.h" +#include "ht-cleanup.h" #define CONSUMERD_FILE "lttng-consumerd" const char *progname; -static const char *tracing_group_name = DEFAULT_TRACING_GROUP; +const char *tracing_group_name = DEFAULT_TRACING_GROUP; static int tracing_group_name_override; static char *opt_pidfile; static int opt_sig_parent; @@ -102,6 +106,7 @@ static struct consumer_data kconsumer_data = { .cmd_unix_sock_path = DEFAULT_KCONSUMERD_CMD_SOCK_PATH, .err_sock = -1, .cmd_sock = -1, + .channel_monitor_pipe = -1, .pid_mutex = PTHREAD_MUTEX_INITIALIZER, .lock = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, @@ -113,6 +118,7 @@ static struct consumer_data ustconsumer64_data = { .cmd_unix_sock_path = DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH, .err_sock = -1, .cmd_sock = -1, + .channel_monitor_pipe = -1, .pid_mutex = PTHREAD_MUTEX_INITIALIZER, .lock = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, @@ -124,6 +130,7 @@ static struct consumer_data ustconsumer32_data = { .cmd_unix_sock_path = DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH, .err_sock = -1, .cmd_sock = -1, + .channel_monitor_pipe = -1, .pid_mutex = PTHREAD_MUTEX_INITIALIZER, .lock = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, @@ -189,7 +196,6 @@ static int kernel_poll_pipe[2] = { -1, -1 }; * for all threads when receiving an event on the pipe. */ static int thread_quit_pipe[2] = { -1, -1 }; -static int ht_cleanup_quit_pipe[2] = { -1, -1 }; /* * This pipe is used to inform the thread managing application communication @@ -210,6 +216,7 @@ static pthread_t health_thread; static pthread_t ht_cleanup_thread; static pthread_t agent_reg_thread; static pthread_t load_session_thread; +static pthread_t notification_thread; /* * UST registration command queue. This queue is tied with a futex and uses a N @@ -304,17 +311,26 @@ const char * const config_section_name = "sessiond"; /* Load session thread information to operate. */ struct load_session_thread_data *load_info; +/* Notification thread handle. */ +struct notification_thread_handle *notification_thread_handle; + /* Global hash tables */ struct lttng_ht *agent_apps_ht_by_sock = NULL; /* - * Whether sessiond is ready for commands/health check requests. + * Whether sessiond is ready for commands/notification channel/health check + * requests. * NR_LTTNG_SESSIOND_READY must match the number of calls to * sessiond_notify_ready(). */ -#define NR_LTTNG_SESSIOND_READY 3 +#define NR_LTTNG_SESSIOND_READY 4 int lttng_sessiond_ready = NR_LTTNG_SESSIOND_READY; +int sessiond_check_thread_quit_pipe(int fd, uint32_t events) +{ + return (fd == thread_quit_pipe[0] && (events & LPOLLIN)) ? 1 : 0; +} + /* Notify parents that we are ready for cmd and health check */ LTTNG_HIDDEN void sessiond_notify_ready(void) @@ -421,47 +437,6 @@ int sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size) return __sessiond_set_thread_pollset(events, size, thread_quit_pipe); } -/* - * Create a poll set with O_CLOEXEC and add the thread quit pipe to the set. - */ -int sessiond_set_ht_cleanup_thread_pollset(struct lttng_poll_event *events, - size_t size) -{ - return __sessiond_set_thread_pollset(events, size, - ht_cleanup_quit_pipe); -} - -static -int __sessiond_check_thread_quit_pipe(int fd, uint32_t events, int a_pipe) -{ - if (fd == a_pipe && (events & LPOLLIN)) { - return 1; - } - return 0; -} - -/* - * Check if the thread quit pipe was triggered. - * - * Return 1 if it was triggered else 0; - */ -int sessiond_check_thread_quit_pipe(int fd, uint32_t events) -{ - return __sessiond_check_thread_quit_pipe(fd, events, - thread_quit_pipe[0]); -} - -/* - * Check if the ht_cleanup thread quit pipe was triggered. - * - * Return 1 if it was triggered else 0; - */ -int sessiond_check_ht_cleanup_quit(int fd, uint32_t events) -{ - return __sessiond_check_thread_quit_pipe(fd, events, - ht_cleanup_quit_pipe[0]); -} - /* * Init thread quit pipe. * @@ -494,11 +469,6 @@ static int init_thread_quit_pipe(void) return __init_thread_quit_pipe(thread_quit_pipe); } -static int init_ht_cleanup_quit_pipe(void) -{ - return __init_thread_quit_pipe(ht_cleanup_quit_pipe); -} - /* * Stop all threads by closing the thread quit pipe. */ @@ -561,6 +531,24 @@ static void close_consumer_sockets(void) PERROR("UST consumerd64 cmd_sock close"); } } + if (kconsumer_data.channel_monitor_pipe >= 0) { + ret = close(kconsumer_data.channel_monitor_pipe); + if (ret < 0) { + PERROR("kernel consumer channel monitor pipe close"); + } + } + if (ustconsumer32_data.channel_monitor_pipe >= 0) { + ret = close(ustconsumer32_data.channel_monitor_pipe); + if (ret < 0) { + PERROR("UST consumerd32 channel monitor pipe close"); + } + } + if (ustconsumer64_data.channel_monitor_pipe >= 0) { + ret = close(ustconsumer64_data.channel_monitor_pipe); + if (ret < 0) { + PERROR("UST consumerd64 channel monitor pipe close"); + } + } } /* @@ -800,12 +788,6 @@ static void sessiond_cleanup_options(void) free(kmod_extra_probes_list); run_as_destroy_worker(); - - /* */ - DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm" - "Matthew, BEET driven development works!%c[%dm", - 27, 1, 31, 27, 0, 27, 1, 33, 27, 0); - /* */ } /* @@ -1270,6 +1252,7 @@ static void *thread_manage_consumer(void *data) enum lttcomm_return_code code; struct lttng_poll_event events; struct consumer_data *consumer_data = data; + struct consumer_socket *cmd_socket_wrapper = NULL; DBG("[thread] Manage consumer started"); @@ -1379,40 +1362,43 @@ restart: } health_code_update(); - if (code == LTTCOMM_CONSUMERD_COMMAND_SOCK_READY) { - /* Connect both socket, command and metadata. */ - consumer_data->cmd_sock = - lttcomm_connect_unix_sock(consumer_data->cmd_unix_sock_path); - consumer_data->metadata_fd = - lttcomm_connect_unix_sock(consumer_data->cmd_unix_sock_path); - if (consumer_data->cmd_sock < 0 - || consumer_data->metadata_fd < 0) { - PERROR("consumer connect cmd socket"); - /* On error, signal condition and quit. */ - signal_consumer_condition(consumer_data, -1); - goto error; - } - consumer_data->metadata_sock.fd_ptr = &consumer_data->metadata_fd; - /* Create metadata socket lock. */ - consumer_data->metadata_sock.lock = zmalloc(sizeof(pthread_mutex_t)); - if (consumer_data->metadata_sock.lock == NULL) { - PERROR("zmalloc pthread mutex"); - ret = -1; - goto error; - } - pthread_mutex_init(consumer_data->metadata_sock.lock, NULL); - - signal_consumer_condition(consumer_data, 1); - DBG("Consumer command socket ready (fd: %d", consumer_data->cmd_sock); - DBG("Consumer metadata socket ready (fd: %d)", - consumer_data->metadata_fd); - } else { + if (code != LTTCOMM_CONSUMERD_COMMAND_SOCK_READY) { ERR("consumer error when waiting for SOCK_READY : %s", lttcomm_get_readable_code(-code)); goto error; } - /* Remove the consumerd error sock since we've established a connexion */ + /* Connect both command and metadata sockets. */ + consumer_data->cmd_sock = + lttcomm_connect_unix_sock( + consumer_data->cmd_unix_sock_path); + consumer_data->metadata_fd = + lttcomm_connect_unix_sock( + consumer_data->cmd_unix_sock_path); + if (consumer_data->cmd_sock < 0 || consumer_data->metadata_fd < 0) { + PERROR("consumer connect cmd socket"); + /* On error, signal condition and quit. */ + signal_consumer_condition(consumer_data, -1); + goto error; + } + + consumer_data->metadata_sock.fd_ptr = &consumer_data->metadata_fd; + + /* Create metadata socket lock. */ + consumer_data->metadata_sock.lock = zmalloc(sizeof(pthread_mutex_t)); + if (consumer_data->metadata_sock.lock == NULL) { + PERROR("zmalloc pthread mutex"); + goto error; + } + pthread_mutex_init(consumer_data->metadata_sock.lock, NULL); + + DBG("Consumer command socket ready (fd: %d", consumer_data->cmd_sock); + DBG("Consumer metadata socket ready (fd: %d)", + consumer_data->metadata_fd); + + /* + * Remove the consumerd error sock since we've established a connection. + */ ret = lttng_poll_del(&events, consumer_data->err_sock); if (ret < 0) { goto error; @@ -1433,6 +1419,27 @@ restart: health_code_update(); + /* + * Transfer the write-end of the channel monitoring pipe to the + * by issuing a SET_CHANNEL_MONITOR_PIPE command. + */ + cmd_socket_wrapper = consumer_allocate_socket(&consumer_data->cmd_sock); + if (!cmd_socket_wrapper) { + goto error; + } + + ret = consumer_send_channel_monitor_pipe(cmd_socket_wrapper, + consumer_data->channel_monitor_pipe); + if (ret) { + goto error; + } + /* Discard the socket wrapper as it is no longer needed. */ + consumer_destroy_socket(cmd_socket_wrapper); + cmd_socket_wrapper = NULL; + + /* The thread is completely initialized, signal that it is ready. */ + signal_consumer_condition(consumer_data, 1); + /* Infinite blocking call, waiting for transmission */ restart_poll: while (1) { @@ -1576,6 +1583,10 @@ error: free(consumer_data->metadata_sock.lock); } lttng_poll_clean(&events); + + if (cmd_socket_wrapper) { + consumer_destroy_socket(cmd_socket_wrapper); + } error_poll: if (err) { health_error(); @@ -1902,6 +1913,8 @@ static void *thread_dispatch_ust_registration(void *data) .count = 0, }; + rcu_register_thread(); + health_register(health_sessiond, HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH); if (testpoint(sessiond_thread_app_reg_dispatch)) { @@ -2135,6 +2148,7 @@ error_testpoint: ERR("Health error occurred in %s", __func__); } health_unregister(health_sessiond); + rcu_unregister_thread(); return NULL; } @@ -2242,10 +2256,12 @@ static void *thread_registration_apps(void *data) * lttcomm_setsockopt_snd_timeout expect msec as * parameter. */ - (void) lttcomm_setsockopt_rcv_timeout(sock, - app_socket_timeout * 1000); - (void) lttcomm_setsockopt_snd_timeout(sock, - app_socket_timeout * 1000); + if (app_socket_timeout >= 0) { + (void) lttcomm_setsockopt_rcv_timeout(sock, + app_socket_timeout * 1000); + (void) lttcomm_setsockopt_snd_timeout(sock, + app_socket_timeout * 1000); + } /* * Set the CLOEXEC flag. Return code is useless because @@ -2406,8 +2422,8 @@ static int spawn_consumer_thread(struct consumer_data *consumer_data) goto error; } - ret = pthread_create(&consumer_data->thread, NULL, thread_manage_consumer, - consumer_data); + ret = pthread_create(&consumer_data->thread, default_pthread_attr(), + thread_manage_consumer, consumer_data); if (ret) { errno = ret; PERROR("pthread_create consumer"); @@ -2419,7 +2435,7 @@ static int spawn_consumer_thread(struct consumer_data *consumer_data) pthread_mutex_lock(&consumer_data->cond_mutex); /* Get time for sem_timedwait absolute timeout */ - clock_ret = clock_gettime(CLOCK_MONOTONIC, &timeout); + clock_ret = lttng_clock_gettime(CLOCK_MONOTONIC, &timeout); /* * Set the timeout for the condition timed wait even if the clock gettime * call fails since we might loop on that call and we want to avoid to @@ -3044,7 +3060,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, case LTTNG_SNAPSHOT_RECORD: case LTTNG_SAVE_SESSION: case LTTNG_SET_SESSION_SHM_PATH: - case LTTNG_METADATA_REGENERATE: + case LTTNG_REGENERATE_METADATA: + case LTTNG_REGENERATE_STATEDUMP: + case LTTNG_REGISTER_TRIGGER: + case LTTNG_UNREGISTER_TRIGGER: need_domain = 0; break; default: @@ -3102,12 +3121,13 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, case LTTNG_CREATE_SESSION: case LTTNG_CREATE_SESSION_SNAPSHOT: case LTTNG_CREATE_SESSION_LIVE: - case LTTNG_CALIBRATE: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: case LTTNG_LIST_SYSCALLS: case LTTNG_LIST_TRACEPOINT_FIELDS: case LTTNG_SAVE_SESSION: + case LTTNG_REGISTER_TRIGGER: + case LTTNG_UNREGISTER_TRIGGER: need_tracing_session = 0; break; default: @@ -3491,8 +3511,11 @@ error_add_context: } case LTTNG_ENABLE_CHANNEL: { + cmd_ctx->lsm->u.channel.chan.attr.extended.ptr = + (struct lttng_channel_extended *) &cmd_ctx->lsm->u.channel.extended; ret = cmd_enable_channel(cmd_ctx->session, &cmd_ctx->lsm->domain, - &cmd_ctx->lsm->u.channel.chan, kernel_poll_pipe[1]); + &cmd_ctx->lsm->u.channel.chan, + kernel_poll_pipe[1]); break; } case LTTNG_TRACK_PID: @@ -3944,12 +3967,6 @@ error_add_context: ret = LTTNG_OK; break; } - case LTTNG_CALIBRATE: - { - ret = cmd_calibrate(cmd_ctx->lsm->domain.type, - &cmd_ctx->lsm->u.calibrate); - break; - } case LTTNG_REGISTER_CONSUMER: { struct consumer_data *cdata; @@ -4155,9 +4172,26 @@ error_add_context: cmd_ctx->lsm->u.set_shm_path.shm_path); break; } - case LTTNG_METADATA_REGENERATE: + case LTTNG_REGENERATE_METADATA: + { + ret = cmd_regenerate_metadata(cmd_ctx->session); + break; + } + case LTTNG_REGENERATE_STATEDUMP: + { + ret = cmd_regenerate_statedump(cmd_ctx->session); + break; + } + case LTTNG_REGISTER_TRIGGER: { - ret = cmd_metadata_regenerate(cmd_ctx->session); + ret = cmd_register_trigger(cmd_ctx, sock, + notification_thread_handle); + break; + } + case LTTNG_UNREGISTER_TRIGGER: + { + ret = cmd_unregister_trigger(cmd_ctx, sock, + notification_thread_handle); break; } default: @@ -4326,7 +4360,6 @@ restart: if (ret) { PERROR("close"); } - new_sock = -1; continue; } @@ -4355,7 +4388,6 @@ restart: if (ret) { PERROR("close"); } - new_sock = -1; } exit: @@ -4373,7 +4405,7 @@ error: } lttng_poll_clean(&events); - + stop_threads(); rcu_unregister_thread(); return NULL; } @@ -5411,9 +5443,6 @@ error: static void sighandler(int sig) { switch (sig) { - case SIGPIPE: - DBG("SIGPIPE caught"); - return; case SIGINT: DBG("SIGINT caught"); stop_threads(); @@ -5445,9 +5474,10 @@ static int set_signal_handler(void) return ret; } - sa.sa_handler = sighandler; sa.sa_mask = sigset; sa.sa_flags = 0; + + sa.sa_handler = sighandler; if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) { PERROR("sigaction"); return ret; @@ -5458,12 +5488,13 @@ static int set_signal_handler(void) return ret; } - if ((ret = sigaction(SIGPIPE, &sa, NULL)) < 0) { + if ((ret = sigaction(SIGUSR1, &sa, NULL)) < 0) { PERROR("sigaction"); return ret; } - if ((ret = sigaction(SIGUSR1, &sa, NULL)) < 0) { + sa.sa_handler = SIG_IGN; + if ((ret = sigaction(SIGPIPE, &sa, NULL)) < 0) { PERROR("sigaction"); return ret; } @@ -5577,6 +5608,9 @@ int main(int argc, char **argv) int ret = 0, retval = 0; void *status; const char *home_path, *env_app_timeout; + struct lttng_pipe *ust32_channel_monitor_pipe = NULL, + *ust64_channel_monitor_pipe = NULL, + *kernel_channel_monitor_pipe = NULL; init_kernel_workarounds(); @@ -5651,23 +5685,8 @@ int main(int argc, char **argv) goto exit_health_sessiond_cleanup; } - if (init_ht_cleanup_quit_pipe()) { - retval = -1; - goto exit_ht_cleanup_quit_pipe; - } - - /* Setup the thread ht_cleanup communication pipe. */ - if (utils_create_pipe_cloexec(ht_cleanup_pipe)) { - retval = -1; - goto exit_ht_cleanup_pipe; - } - /* Create thread to clean up RCU hash tables */ - ret = pthread_create(&ht_cleanup_thread, NULL, - thread_ht_cleanup, (void *) NULL); - if (ret) { - errno = ret; - PERROR("pthread_create ht_cleanup"); + if (init_ht_cleanup_thread(&ht_cleanup_thread)) { retval = -1; goto exit_ht_cleanup; } @@ -5750,6 +5769,19 @@ int main(int argc, char **argv) kconsumer_data.err_unix_sock_path); DBG2("Kernel consumer cmd path: %s", kconsumer_data.cmd_unix_sock_path); + kernel_channel_monitor_pipe = lttng_pipe_open(0); + if (!kernel_channel_monitor_pipe) { + ERR("Failed to create kernel consumer channel monitor pipe"); + retval = -1; + goto exit_init_data; + } + kconsumer_data.channel_monitor_pipe = + lttng_pipe_release_writefd( + kernel_channel_monitor_pipe); + if (kconsumer_data.channel_monitor_pipe < 0) { + retval = -1; + goto exit_init_data; + } } else { home_path = utils_get_home_dir(); if (home_path == NULL) { @@ -5854,6 +5886,18 @@ int main(int argc, char **argv) ustconsumer32_data.err_unix_sock_path); DBG2("UST consumer 32 bits cmd path: %s", ustconsumer32_data.cmd_unix_sock_path); + ust32_channel_monitor_pipe = lttng_pipe_open(0); + if (!ust32_channel_monitor_pipe) { + ERR("Failed to create 32-bit user space consumer channel monitor pipe"); + retval = -1; + goto exit_init_data; + } + ustconsumer32_data.channel_monitor_pipe = lttng_pipe_release_writefd( + ust32_channel_monitor_pipe); + if (ustconsumer32_data.channel_monitor_pipe < 0) { + retval = -1; + goto exit_init_data; + } /* 64 bits consumerd path setup */ ret = snprintf(ustconsumer64_data.err_unix_sock_path, PATH_MAX, @@ -5875,6 +5919,18 @@ int main(int argc, char **argv) ustconsumer64_data.err_unix_sock_path); DBG2("UST consumer 64 bits cmd path: %s", ustconsumer64_data.cmd_unix_sock_path); + ust64_channel_monitor_pipe = lttng_pipe_open(0); + if (!ust64_channel_monitor_pipe) { + ERR("Failed to create 64-bit user space consumer channel monitor pipe"); + retval = -1; + goto exit_init_data; + } + ustconsumer64_data.channel_monitor_pipe = lttng_pipe_release_writefd( + ust64_channel_monitor_pipe); + if (ustconsumer64_data.channel_monitor_pipe < 0) { + retval = -1; + goto exit_init_data; + } /* * See if daemon already exist. @@ -6034,8 +6090,8 @@ int main(int argc, char **argv) } load_info->path = opt_load_session_path; - /* Create health-check thread */ - ret = pthread_create(&health_thread, NULL, + /* Create health-check thread. */ + ret = pthread_create(&health_thread, default_pthread_attr(), thread_manage_health, (void *) NULL); if (ret) { errno = ret; @@ -6044,86 +6100,117 @@ int main(int argc, char **argv) goto exit_health; } + /* notification_thread_data acquires the pipes' read side. */ + notification_thread_handle = notification_thread_handle_create( + ust32_channel_monitor_pipe, + ust64_channel_monitor_pipe, + kernel_channel_monitor_pipe); + if (!notification_thread_handle) { + retval = -1; + ERR("Failed to create notification thread shared data"); + stop_threads(); + goto exit_notification; + } + + /* Create notification thread. */ + ret = pthread_create(¬ification_thread, default_pthread_attr(), + thread_notification, notification_thread_handle); + if (ret) { + errno = ret; + PERROR("pthread_create notification"); + retval = -1; + stop_threads(); + goto exit_notification; + } + /* Create thread to manage the client socket */ - ret = pthread_create(&client_thread, NULL, + ret = pthread_create(&client_thread, default_pthread_attr(), thread_manage_clients, (void *) NULL); if (ret) { errno = ret; PERROR("pthread_create clients"); retval = -1; + stop_threads(); goto exit_client; } /* Create thread to dispatch registration */ - ret = pthread_create(&dispatch_thread, NULL, + ret = pthread_create(&dispatch_thread, default_pthread_attr(), thread_dispatch_ust_registration, (void *) NULL); if (ret) { errno = ret; PERROR("pthread_create dispatch"); retval = -1; + stop_threads(); goto exit_dispatch; } /* Create thread to manage application registration. */ - ret = pthread_create(®_apps_thread, NULL, + ret = pthread_create(®_apps_thread, default_pthread_attr(), thread_registration_apps, (void *) NULL); if (ret) { errno = ret; PERROR("pthread_create registration"); retval = -1; + stop_threads(); goto exit_reg_apps; } /* Create thread to manage application socket */ - ret = pthread_create(&apps_thread, NULL, + ret = pthread_create(&apps_thread, default_pthread_attr(), thread_manage_apps, (void *) NULL); if (ret) { errno = ret; PERROR("pthread_create apps"); retval = -1; + stop_threads(); goto exit_apps; } /* Create thread to manage application notify socket */ - ret = pthread_create(&apps_notify_thread, NULL, + ret = pthread_create(&apps_notify_thread, default_pthread_attr(), ust_thread_manage_notify, (void *) NULL); if (ret) { errno = ret; PERROR("pthread_create notify"); retval = -1; + stop_threads(); goto exit_apps_notify; } /* Create agent registration thread. */ - ret = pthread_create(&agent_reg_thread, NULL, + ret = pthread_create(&agent_reg_thread, default_pthread_attr(), agent_thread_manage_registration, (void *) NULL); if (ret) { errno = ret; PERROR("pthread_create agent"); retval = -1; + stop_threads(); goto exit_agent_reg; } /* Don't start this thread if kernel tracing is not requested nor root */ if (is_root && !opt_no_kernel) { /* Create kernel thread to manage kernel event */ - ret = pthread_create(&kernel_thread, NULL, + ret = pthread_create(&kernel_thread, default_pthread_attr(), thread_manage_kernel, (void *) NULL); if (ret) { errno = ret; PERROR("pthread_create kernel"); retval = -1; + stop_threads(); goto exit_kernel; } } /* Create session loading thread. */ - ret = pthread_create(&load_session_thread, NULL, thread_load_session, - load_info); + ret = pthread_create(&load_session_thread, default_pthread_attr(), + thread_load_session, load_info); if (ret) { errno = ret; PERROR("pthread_create load_session_thread"); retval = -1; + stop_threads(); goto exit_load_session; } @@ -6200,25 +6287,30 @@ exit_dispatch: PERROR("pthread_join"); retval = -1; } -exit_client: +exit_client: +exit_notification: ret = pthread_join(health_thread, &status); if (ret) { errno = ret; PERROR("pthread_join health thread"); retval = -1; } -exit_health: +exit_health: exit_init_data: + /* + * Wait for all pending call_rcu work to complete before tearing + * down data structures. call_rcu worker may be trying to + * perform lookups in those structures. + */ + rcu_barrier(); /* * sessiond_cleanup() is called when no other thread is running, except * the ht_cleanup thread, which is needed to destroy the hash tables. */ rcu_thread_online(); sessiond_cleanup(); - rcu_thread_offline(); - rcu_unregister_thread(); /* * Ensure all prior call_rcu are done. call_rcu callbacks may push @@ -6227,28 +6319,34 @@ exit_init_data: */ rcu_barrier(); - ret = notify_thread_pipe(ht_cleanup_quit_pipe[1]); - if (ret < 0) { - ERR("write error on ht_cleanup quit pipe"); - retval = -1; + /* + * The teardown of the notification system is performed after the + * session daemon's teardown in order to allow it to be notified + * of the active session and channels at the moment of the teardown. + */ + if (notification_thread_handle) { + notification_thread_command_quit(notification_thread_handle); + notification_thread_handle_destroy(notification_thread_handle); } - ret = pthread_join(ht_cleanup_thread, &status); + ret = pthread_join(notification_thread, &status); if (ret) { errno = ret; - PERROR("pthread_join ht cleanup thread"); + PERROR("pthread_join notification thread"); retval = -1; } -exit_ht_cleanup: - utils_close_pipe(ht_cleanup_pipe); -exit_ht_cleanup_pipe: + rcu_thread_offline(); + rcu_unregister_thread(); - /* - * Close the ht_cleanup quit pipe. - */ - utils_close_pipe(ht_cleanup_quit_pipe); -exit_ht_cleanup_quit_pipe: + ret = fini_ht_cleanup_thread(&ht_cleanup_thread); + if (ret) { + retval = -1; + } + lttng_pipe_destroy(ust32_channel_monitor_pipe); + lttng_pipe_destroy(ust64_channel_monitor_pipe); + lttng_pipe_destroy(kernel_channel_monitor_pipe); +exit_ht_cleanup: health_app_destroy(health_sessiond); exit_health_sessiond_cleanup: @@ -6258,7 +6356,6 @@ exit_options: sessiond_cleanup_options(); exit_set_signal_handler: - if (!retval) { exit(EXIT_SUCCESS); } else {