X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=ltt-sessiond%2Fmain.c;h=2c2fe44bf52771c54415e58766f03bd385e4c9ec;hp=825fa4371cb67b0316fcf9ce8b6e677dd1f0f115;hb=1316184615e422526ef4fae68f980443414969c1;hpb=44d3bd014f6ad217cff7e7c3dfaad76b1927c37b diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 825fa4371..2c2fe44bf 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -36,10 +36,12 @@ #include #include #include +#include -#include +#include #include -#include +#include + #include #include "channel.h" @@ -47,13 +49,31 @@ #include "context.h" #include "event.h" #include "futex.h" +#include "hashtable.h" #include "kernel-ctl.h" #include "ltt-sessiond.h" #include "shm.h" -#include "traceable-app.h" +#include "ust-app.h" #include "ust-ctl.h" #include "utils.h" -#include "ust-ctl.h" + +struct consumer_data { + enum lttng_consumer_type type; + + pthread_t thread; /* Worker thread interacting with the consumer */ + sem_t sem; + + /* Mutex to control consumerd pid assignation */ + pthread_mutex_t pid_mutex; + pid_t pid; + + int err_sock; + int cmd_sock; + + /* consumer error and command Unix socket path */ + char err_unix_sock_path[PATH_MAX]; + char cmd_unix_sock_path[PATH_MAX]; +}; /* Const values */ const char default_home_dir[] = DEFAULT_HOME_DIR; @@ -63,7 +83,7 @@ const char default_global_apps_pipe[] = DEFAULT_GLOBAL_APPS_PIPE; /* Variables */ int opt_verbose; /* Not static for lttngerr.h */ -int opt_verbose_kconsumerd; /* Not static for lttngerr.h */ +int opt_verbose_consumer; /* Not static for lttngerr.h */ int opt_quiet; /* Not static for lttngerr.h */ const char *progname; @@ -72,24 +92,27 @@ static int opt_sig_parent; static int opt_daemon; static int is_root; /* Set to 1 if the daemon is running as root */ static pid_t ppid; /* Parent PID for --sig-parent option */ -static pid_t kconsumerd_pid; + +/* Consumer daemon specific control data */ +static struct consumer_data kconsumer_data = { + .type = LTTNG_CONSUMER_KERNEL, +}; +static struct consumer_data ustconsumer_data = { + .type = LTTNG_CONSUMER_UST, +}; + static int dispatch_thread_exit; /* Global application Unix socket path */ static char apps_unix_sock_path[PATH_MAX]; /* Global client Unix socket path */ static char client_unix_sock_path[PATH_MAX]; -/* kconsumerd error and command Unix socket path */ -static char kconsumerd_err_unix_sock_path[PATH_MAX]; -static char kconsumerd_cmd_unix_sock_path[PATH_MAX]; /* global wait shm path for UST */ static char wait_shm_path[PATH_MAX]; /* Sockets and FDs */ static int client_sock; static int apps_sock; -static int kconsumerd_err_sock; -static int kconsumerd_cmd_sock; static int kernel_tracer_fd; static int kernel_poll_pipe[2]; @@ -106,18 +129,13 @@ static int thread_quit_pipe[2]; static int apps_cmd_pipe[2]; /* Pthread, Mutexes and Semaphores */ -static pthread_t kconsumerd_thread; static pthread_t apps_thread; static pthread_t reg_apps_thread; static pthread_t client_thread; static pthread_t kernel_thread; static pthread_t dispatch_thread; -static sem_t kconsumerd_sem; -/* Mutex to control kconsumerd pid assignation */ -static pthread_mutex_t kconsumerd_pid_mutex; - /* * UST registration command queue. This queue is tied with a futex and uses a N * wakers / 1 waiter implemented and detailed in futex.c/.h @@ -193,16 +211,16 @@ static int modprobe_remove_kernel_modules(void) for (i = ARRAY_SIZE(kernel_modules_list) - 1; i >= 0; i--) { ret = snprintf(modprobe, sizeof(modprobe), - "/sbin/modprobe --remove --quiet %s", + "/sbin/modprobe -r -q %s", kernel_modules_list[i].name); if (ret < 0) { - perror("snprintf modprobe --remove"); + perror("snprintf modprobe -r"); goto error; } modprobe[sizeof(modprobe) - 1] = '\0'; ret = system(modprobe); if (ret == -1) { - ERR("Unable to launch modprobe --remove for module %s", + ERR("Unable to launch modprobe -r for module %s", kernel_modules_list[i].name); } else if (kernel_modules_list[i].required && WEXITSTATUS(ret) != 0) { @@ -269,7 +287,7 @@ static void teardown_kernel_session(struct ltt_session *session) * If a custom kernel consumer was registered, close the socket before * tearing down the complete kernel session structure */ - if (session->kernel_session->consumer_fd != kconsumerd_cmd_sock) { + if (session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) { lttcomm_close_unix_sock(session->kernel_session->consumer_fd); } @@ -279,6 +297,17 @@ static void teardown_kernel_session(struct ltt_session *session) } } +/* + * Complete teardown of all UST sessions. This will free everything on his path + * and destroy the core essence of all ust sessions :) + */ +static void teardown_ust_session(struct ltt_session *session) +{ + DBG("Tearing down UST session(s)"); + + trace_ust_destroy_session(session->ust_session); +} + /* * Stop all threads by closing the thread quit pipe. */ @@ -339,14 +368,15 @@ static void cleanup(void) cds_list_for_each_entry_safe(sess, stmp, &session_list_ptr->head, list) { teardown_kernel_session(sess); - // TODO complete session cleanup (including UST) + teardown_ust_session(sess); + free(sess); } } DBG("Closing all UST sockets"); - clean_traceable_apps_list(); + ust_app_clean_list(); - pthread_mutex_destroy(&kconsumerd_pid_mutex); + pthread_mutex_destroy(&kconsumer_data.pid_mutex); DBG("Closing kernel fd"); close(kernel_tracer_fd); @@ -396,54 +426,55 @@ static void clean_command_ctx(struct command_ctx **cmd_ctx) /* * Send all stream fds of kernel channel to the consumer. */ -static int send_kconsumerd_channel_fds(int sock, - struct ltt_kernel_channel *channel) +static int send_kconsumer_channel_streams(struct consumer_data *consumer_data, + int sock, struct ltt_kernel_channel *channel) { int ret; - size_t nb_fd; struct ltt_kernel_stream *stream; - struct lttcomm_kconsumerd_header lkh; - struct lttcomm_kconsumerd_msg lkm; + struct lttcomm_consumer_msg lkm; - DBG("Sending fds of channel %s to kernel consumer", + DBG("Sending streams of channel %s to kernel consumer", channel->channel->name); - nb_fd = channel->stream_count; - - /* Setup header */ - lkh.payload_size = nb_fd * sizeof(struct lttcomm_kconsumerd_msg); - lkh.cmd_type = ADD_STREAM; - - DBG("Sending kconsumerd header"); - - ret = lttcomm_send_unix_sock(sock, &lkh, - sizeof(struct lttcomm_kconsumerd_header)); + /* Send channel */ + lkm.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL; + lkm.u.channel.channel_key = channel->fd; + lkm.u.channel.max_sb_size = channel->channel->attr.subbuf_size; + lkm.u.channel.mmap_len = 0; /* for kernel */ + DBG("Sending channel %d to consumer", lkm.u.channel.channel_key); + ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm)); if (ret < 0) { - perror("send kconsumerd header"); + perror("send consumer channel"); goto error; } + /* Send streams */ cds_list_for_each_entry(stream, &channel->stream_list.head, list) { - if (stream->fd != 0) { - lkm.fd = stream->fd; - lkm.state = stream->state; - lkm.max_sb_size = channel->channel->attr.subbuf_size; - lkm.output = channel->channel->attr.output; - strncpy(lkm.path_name, stream->pathname, PATH_MAX); - lkm.path_name[PATH_MAX - 1] = '\0'; - - DBG("Sending fd %d to kconsumerd", lkm.fd); - - ret = lttcomm_send_fds_unix_sock(sock, &lkm, - &lkm.fd, 1, sizeof(lkm)); - if (ret < 0) { - perror("send kconsumerd fd"); - goto error; - } + if (!stream->fd) { + continue; + } + lkm.cmd_type = LTTNG_CONSUMER_ADD_STREAM; + lkm.u.stream.channel_key = channel->fd; + lkm.u.stream.stream_key = stream->fd; + lkm.u.stream.state = stream->state; + lkm.u.stream.output = channel->channel->attr.output; + lkm.u.stream.mmap_len = 0; /* for kernel */ + strncpy(lkm.u.stream.path_name, stream->pathname, PATH_MAX - 1); + lkm.u.stream.path_name[PATH_MAX - 1] = '\0'; + DBG("Sending stream %d to consumer", lkm.u.stream.stream_key); + ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm)); + if (ret < 0) { + perror("send consumer stream"); + goto error; + } + ret = lttcomm_send_fds_unix_sock(sock, &stream->fd, 1); + if (ret < 0) { + perror("send consumer stream ancillary data"); + goto error; } } - DBG("Kconsumerd channel fds sent"); + DBG("consumer channel streams sent"); return 0; @@ -454,58 +485,64 @@ error: /* * Send all stream fds of the kernel session to the consumer. */ -static int send_kconsumerd_fds(struct ltt_kernel_session *session) +static int send_kconsumer_session_streams(struct consumer_data *consumer_data, + struct ltt_kernel_session *session) { int ret; struct ltt_kernel_channel *chan; - struct lttcomm_kconsumerd_header lkh; - struct lttcomm_kconsumerd_msg lkm; - - /* Setup header */ - lkh.payload_size = sizeof(struct lttcomm_kconsumerd_msg); - lkh.cmd_type = ADD_STREAM; - - DBG("Sending kconsumerd header for metadata"); - - ret = lttcomm_send_unix_sock(session->consumer_fd, &lkh, - sizeof(struct lttcomm_kconsumerd_header)); - if (ret < 0) { - perror("send kconsumerd header"); - goto error; - } + struct lttcomm_consumer_msg lkm; + int sock = session->consumer_fd; DBG("Sending metadata stream fd"); - /* Extra protection. It's NOT suppose to be set to 0 at this point */ + /* Extra protection. It's NOT supposed to be set to 0 at this point */ if (session->consumer_fd == 0) { - session->consumer_fd = kconsumerd_cmd_sock; + session->consumer_fd = consumer_data->cmd_sock; } if (session->metadata_stream_fd != 0) { - /* Send metadata stream fd first */ - lkm.fd = session->metadata_stream_fd; - lkm.state = ACTIVE_FD; - lkm.max_sb_size = session->metadata->conf->attr.subbuf_size; - lkm.output = DEFAULT_KERNEL_CHANNEL_OUTPUT; - strncpy(lkm.path_name, session->metadata->pathname, PATH_MAX); - lkm.path_name[PATH_MAX - 1] = '\0'; - - ret = lttcomm_send_fds_unix_sock(session->consumer_fd, &lkm, - &lkm.fd, 1, sizeof(lkm)); + /* Send metadata channel fd */ + lkm.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL; + lkm.u.channel.channel_key = session->metadata->fd; + lkm.u.channel.max_sb_size = session->metadata->conf->attr.subbuf_size; + lkm.u.channel.mmap_len = 0; /* for kernel */ + DBG("Sending metadata channel %d to consumer", lkm.u.stream.stream_key); + ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm)); + if (ret < 0) { + perror("send consumer channel"); + goto error; + } + + /* Send metadata stream fd */ + lkm.cmd_type = LTTNG_CONSUMER_ADD_STREAM; + lkm.u.stream.channel_key = session->metadata->fd; + lkm.u.stream.stream_key = session->metadata_stream_fd; + lkm.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM; + lkm.u.stream.output = DEFAULT_KERNEL_CHANNEL_OUTPUT; + lkm.u.stream.mmap_len = 0; /* for kernel */ + strncpy(lkm.u.stream.path_name, session->metadata->pathname, PATH_MAX - 1); + lkm.u.stream.path_name[PATH_MAX - 1] = '\0'; + DBG("Sending metadata stream %d to consumer", lkm.u.stream.stream_key); + ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm)); if (ret < 0) { - perror("send kconsumerd fd"); + perror("send consumer stream"); + goto error; + } + ret = lttcomm_send_fds_unix_sock(sock, &session->metadata_stream_fd, 1); + if (ret < 0) { + perror("send consumer stream"); goto error; } } cds_list_for_each_entry(chan, &session->channel_list.head, list) { - ret = send_kconsumerd_channel_fds(session->consumer_fd, chan); + ret = send_kconsumer_channel_streams(consumer_data, sock, chan); if (ret < 0) { goto error; } } - DBG("Kconsumerd fds (metadata and channel streams) sent"); + DBG("consumer fds (metadata and channel streams) sent"); return 0; @@ -618,7 +655,7 @@ error: * * Useful for CPU hotplug feature. */ -static int update_kernel_stream(int fd) +static int update_kernel_stream(struct consumer_data *consumer_data, int fd) { int ret = 0; struct ltt_session *session; @@ -636,7 +673,7 @@ static int update_kernel_stream(int fd) /* This is not suppose to be 0 but this is an extra security check */ if (session->kernel_session->consumer_fd == 0) { - session->kernel_session->consumer_fd = kconsumerd_cmd_sock; + session->kernel_session->consumer_fd = consumer_data->cmd_sock; } cds_list_for_each_entry(channel, @@ -653,8 +690,8 @@ static int update_kernel_stream(int fd) * that tracing is started so it is safe to send our updated * stream fds. */ - if (session->kernel_session->kconsumer_fds_sent == 1) { - ret = send_kconsumerd_channel_fds( + if (session->kernel_session->consumer_fds_sent == 1) { + ret = send_kconsumer_channel_streams(consumer_data, session->kernel_session->consumer_fd, channel); if (ret < 0) { goto error; @@ -701,6 +738,12 @@ static void *thread_manage_kernel(void *data) while (1) { if (update_poll_flag == 1) { + /* + * Reset number of fd in the poll set. Always 2 since there is the thread + * quit pipe and the kernel pipe. + */ + events.nb_fd = 2; + ret = update_kernel_poll(&events); if (ret < 0) { goto error; @@ -748,7 +791,7 @@ static void *thread_manage_kernel(void *data) * kernel session and updating the kernel consumer */ if (revents & LPOLLIN) { - ret = update_kernel_stream(pollfd); + ret = update_kernel_stream(&kconsumer_data, pollfd); if (ret < 0) { continue; } @@ -773,18 +816,19 @@ error: } /* - * This thread manage the kconsumerd error sent back to the session daemon. + * This thread manage the consumer error sent back to the session daemon. */ -static void *thread_manage_kconsumerd(void *data) +static void *thread_manage_consumer(void *data) { int sock = 0, i, ret, pollfd; uint32_t revents, nb_fd; enum lttcomm_return_code code; struct lttng_poll_event events; + struct consumer_data *consumer_data = data; - DBG("[thread] Manage kconsumerd started"); + DBG("[thread] Manage consumer started"); - ret = lttcomm_listen_unix_sock(kconsumerd_err_sock); + ret = lttcomm_listen_unix_sock(consumer_data->err_sock); if (ret < 0) { goto error; } @@ -798,7 +842,7 @@ static void *thread_manage_kconsumerd(void *data) goto error; } - ret = lttng_poll_add(&events, kconsumerd_err_sock, LPOLLIN | LPOLLRDHUP); + ret = lttng_poll_add(&events, consumer_data->err_sock, LPOLLIN | LPOLLRDHUP); if (ret < 0) { goto error; } @@ -823,19 +867,21 @@ static void *thread_manage_kconsumerd(void *data) } /* Event on the registration socket */ - if (pollfd == kconsumerd_err_sock) { + if (pollfd == consumer_data->err_sock) { if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { - ERR("Kconsumerd err socket poll error"); + ERR("consumer err socket poll error"); goto error; } } } - sock = lttcomm_accept_unix_sock(kconsumerd_err_sock); + sock = lttcomm_accept_unix_sock(consumer_data->err_sock); if (sock < 0) { goto error; } + DBG2("Receiving code from consumer err_sock"); + /* Getting status code from kconsumerd */ ret = lttcomm_recv_unix_sock(sock, &code, sizeof(enum lttcomm_return_code)); @@ -843,25 +889,25 @@ static void *thread_manage_kconsumerd(void *data) goto error; } - if (code == KCONSUMERD_COMMAND_SOCK_READY) { - kconsumerd_cmd_sock = - lttcomm_connect_unix_sock(kconsumerd_cmd_unix_sock_path); - if (kconsumerd_cmd_sock < 0) { - sem_post(&kconsumerd_sem); - perror("kconsumerd connect"); + if (code == CONSUMERD_COMMAND_SOCK_READY) { + consumer_data->cmd_sock = + lttcomm_connect_unix_sock(consumer_data->cmd_unix_sock_path); + if (consumer_data->cmd_sock < 0) { + sem_post(&consumer_data->sem); + PERROR("consumer connect"); goto error; } /* Signal condition to tell that the kconsumerd is ready */ - sem_post(&kconsumerd_sem); - DBG("Kconsumerd command socket ready"); + sem_post(&consumer_data->sem); + DBG("consumer command socket ready"); } else { - DBG("Kconsumerd error when waiting for SOCK_READY : %s", + ERR("consumer error when waiting for SOCK_READY : %s", lttcomm_get_readable_code(-code)); goto error; } /* Remove the kconsumerd error sock since we've established a connexion */ - ret = lttng_poll_del(&events, kconsumerd_err_sock); + ret = lttng_poll_del(&events, consumer_data->err_sock); if (ret < 0) { goto error; } @@ -894,7 +940,7 @@ static void *thread_manage_kconsumerd(void *data) /* Event on the kconsumerd socket */ if (pollfd == sock) { if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { - ERR("Kconsumerd err socket second poll error"); + ERR("consumer err socket second poll error"); goto error; } } @@ -904,21 +950,21 @@ static void *thread_manage_kconsumerd(void *data) ret = lttcomm_recv_unix_sock(sock, &code, sizeof(enum lttcomm_return_code)); if (ret <= 0) { - ERR("Kconsumerd closed the command socket"); + ERR("consumer closed the command socket"); goto error; } - ERR("Kconsumerd return code : %s", lttcomm_get_readable_code(-code)); + ERR("consumer return code : %s", lttcomm_get_readable_code(-code)); error: - DBG("Kconsumerd thread dying"); - close(kconsumerd_err_sock); - close(kconsumerd_cmd_sock); + DBG("consumer thread dying"); + close(consumer_data->err_sock); + close(consumer_data->cmd_sock); close(sock); - unlink(kconsumerd_err_unix_sock_path); - unlink(kconsumerd_cmd_unix_sock_path); - kconsumerd_pid = 0; + unlink(consumer_data->err_unix_sock_path); + unlink(consumer_data->cmd_unix_sock_path); + consumer_data->pid = 0; lttng_poll_clean(&events); @@ -937,6 +983,9 @@ static void *thread_manage_apps(void *data) DBG("[thread] Manage application started"); + rcu_register_thread(); + rcu_thread_online(); + ret = create_thread_poll_set(&events, 2); if (ret < 0) { goto error; @@ -986,7 +1035,7 @@ static void *thread_manage_apps(void *data) } /* Register applicaton to the session daemon */ - ret = register_traceable_app(&ust_cmd.reg_msg, + ret = ust_app_register(&ust_cmd.reg_msg, ust_cmd.sock); if (ret < 0) { /* Only critical ENOMEM error can be returned here */ @@ -999,7 +1048,7 @@ static void *thread_manage_apps(void *data) * If the registration is not possible, we simply * unregister the apps and continue */ - unregister_traceable_app(ust_cmd.sock); + ust_app_unregister(ust_cmd.sock); } else { /* * We just need here to monitor the close of the UST @@ -1028,7 +1077,7 @@ static void *thread_manage_apps(void *data) } /* Socket closed */ - unregister_traceable_app(pollfd); + ust_app_unregister(pollfd); break; } } @@ -1042,6 +1091,8 @@ error: lttng_poll_clean(&events); + rcu_thread_offline(); + rcu_unregister_thread(); return NULL; } @@ -1065,7 +1116,7 @@ static void *thread_dispatch_ust_registration(void *data) /* Dequeue command for registration */ node = cds_wfq_dequeue_blocking(&ust_cmd_queue.queue); if (node == NULL) { - DBG("Waked up but nothing in the UST command queue"); + DBG("Woken up but nothing in the UST command queue"); /* Continue thread execution */ break; } @@ -1251,131 +1302,173 @@ error: } /* - * Start the thread_manage_kconsumerd. This must be done after a kconsumerd + * Start the thread_manage_consumer. This must be done after a lttng-consumerd * exec or it will fails. */ -static int spawn_kconsumerd_thread(void) +static int spawn_consumer_thread(struct consumer_data *consumer_data) { int ret; + struct timespec timeout; + + timeout.tv_sec = DEFAULT_SEM_WAIT_TIMEOUT; + timeout.tv_nsec = 0; /* Setup semaphore */ - sem_init(&kconsumerd_sem, 0, 0); + ret = sem_init(&consumer_data->sem, 0, 0); + if (ret < 0) { + PERROR("sem_init consumer semaphore"); + goto error; + } - ret = pthread_create(&kconsumerd_thread, NULL, - thread_manage_kconsumerd, (void *) NULL); + ret = pthread_create(&consumer_data->thread, NULL, + thread_manage_consumer, consumer_data); if (ret != 0) { - perror("pthread_create kconsumerd"); + PERROR("pthread_create consumer"); + ret = -1; goto error; } - /* Wait for the kconsumerd thread to be ready */ - sem_wait(&kconsumerd_sem); + /* Get time for sem_timedwait absolute timeout */ + ret = clock_gettime(CLOCK_REALTIME, &timeout); + if (ret < 0) { + PERROR("clock_gettime spawn consumer"); + /* Infinite wait for the kconsumerd thread to be ready */ + ret = sem_wait(&consumer_data->sem); + } else { + /* Normal timeout if the gettime was successful */ + timeout.tv_sec += DEFAULT_SEM_WAIT_TIMEOUT; + ret = sem_timedwait(&consumer_data->sem, &timeout); + } + + if (ret < 0) { + if (errno == ETIMEDOUT) { + /* + * Call has timed out so we kill the kconsumerd_thread and return + * an error. + */ + ERR("The consumer thread was never ready. Killing it"); + ret = pthread_cancel(consumer_data->thread); + if (ret < 0) { + PERROR("pthread_cancel consumer thread"); + } + } else { + PERROR("semaphore wait failed consumer thread"); + } + goto error; + } - if (kconsumerd_pid == 0) { + pthread_mutex_lock(&consumer_data->pid_mutex); + if (consumer_data->pid == 0) { ERR("Kconsumerd did not start"); + pthread_mutex_unlock(&consumer_data->pid_mutex); goto error; } + pthread_mutex_unlock(&consumer_data->pid_mutex); return 0; error: - ret = LTTCOMM_KERN_CONSUMER_FAIL; return ret; } /* - * Join kernel consumer thread + * Join consumer thread */ -static int join_kconsumerd_thread(void) +static int join_consumer_thread(struct consumer_data *consumer_data) { void *status; int ret; - if (kconsumerd_pid != 0) { - ret = kill(kconsumerd_pid, SIGTERM); + if (consumer_data->pid != 0) { + ret = kill(consumer_data->pid, SIGTERM); if (ret) { - ERR("Error killing kconsumerd"); + ERR("Error killing consumer daemon"); return ret; } - return pthread_join(kconsumerd_thread, &status); + return pthread_join(consumer_data->thread, &status); } else { return 0; } } /* - * Fork and exec a kernel consumer daemon (kconsumerd). + * Fork and exec a consumer daemon (consumerd). * * Return pid if successful else -1. */ -static pid_t spawn_kconsumerd(void) +static pid_t spawn_consumerd(struct consumer_data *consumer_data) { int ret; pid_t pid; const char *verbosity; - DBG("Spawning kconsumerd"); + DBG("Spawning consumerd"); pid = fork(); if (pid == 0) { /* - * Exec kconsumerd. + * Exec consumerd. */ - if (opt_verbose > 1 || opt_verbose_kconsumerd) { + if (opt_verbose > 1 || opt_verbose_consumer) { verbosity = "--verbose"; } else { verbosity = "--quiet"; } - execl(INSTALL_BIN_PATH "/ltt-kconsumerd", - "ltt-kconsumerd", verbosity, NULL); + switch (consumer_data->type) { + case LTTNG_CONSUMER_KERNEL: + execl(INSTALL_BIN_PATH "/lttng-consumerd", + "lttng-consumerd", verbosity, "-k", NULL); + break; + case LTTNG_CONSUMER_UST: + execl(INSTALL_BIN_PATH "/lttng-consumerd", + "lttng-consumerd", verbosity, "-u", NULL); + break; + default: + perror("unknown consumer type"); + exit(EXIT_FAILURE); + } if (errno != 0) { perror("kernel start consumer exec"); } exit(EXIT_FAILURE); } else if (pid > 0) { ret = pid; - goto error; } else { - perror("kernel start consumer fork"); + perror("start consumer fork"); ret = -errno; - goto error; } - -error: return ret; } /* - * Spawn the kconsumerd daemon and session daemon thread. + * Spawn the consumerd daemon and session daemon thread. */ -static int start_kconsumerd(void) +static int start_consumerd(struct consumer_data *consumer_data) { int ret; - pthread_mutex_lock(&kconsumerd_pid_mutex); - if (kconsumerd_pid != 0) { - pthread_mutex_unlock(&kconsumerd_pid_mutex); + pthread_mutex_lock(&consumer_data->pid_mutex); + if (consumer_data->pid != 0) { + pthread_mutex_unlock(&consumer_data->pid_mutex); goto end; } - ret = spawn_kconsumerd(); + ret = spawn_consumerd(consumer_data); if (ret < 0) { - ERR("Spawning kconsumerd failed"); - ret = LTTCOMM_KERN_CONSUMER_FAIL; - pthread_mutex_unlock(&kconsumerd_pid_mutex); + ERR("Spawning consumerd failed"); + pthread_mutex_unlock(&consumer_data->pid_mutex); goto error; } - /* Setting up the global kconsumerd_pid */ - kconsumerd_pid = ret; - pthread_mutex_unlock(&kconsumerd_pid_mutex); - - DBG("Kconsumerd pid %d", ret); + /* Setting up the consumer_data pid */ + consumer_data->pid = ret; + DBG2("Consumer pid %d", consumer_data->pid); + pthread_mutex_unlock(&consumer_data->pid_mutex); - DBG("Spawning kconsumerd thread"); - ret = spawn_kconsumerd_thread(); + DBG2("Spawning consumer control thread"); + ret = spawn_consumer_thread(consumer_data); if (ret < 0) { - ERR("Fatal error spawning kconsumerd thread"); + ERR("Fatal error spawning consumer control thread"); goto error; } @@ -1397,7 +1490,7 @@ static int modprobe_kernel_modules(void) for (i = 0; i < ARRAY_SIZE(kernel_modules_list); i++) { ret = snprintf(modprobe, sizeof(modprobe), "/sbin/modprobe %s%s", - kernel_modules_list[i].required ? "" : "--quiet ", + kernel_modules_list[i].required ? "" : "-q ", kernel_modules_list[i].name); if (ret < 0) { perror("snprintf modprobe"); @@ -1432,12 +1525,13 @@ static int mount_debugfs(char *path) ret = mkdir_recursive(path, S_IRWXU | S_IRWXG, geteuid(), getegid()); if (ret < 0) { + PERROR("Cannot create debugfs path"); goto error; } ret = mount(type, path, type, 0, NULL); if (ret < 0) { - perror("mount debugfs"); + PERROR("Cannot mount debugfs"); goto error; } @@ -1487,6 +1581,7 @@ static void init_kernel_tracer(void) } ret = mount_debugfs(debugfs_path); if (ret < 0) { + perror("Cannot mount debugfs"); goto error; } } @@ -1535,23 +1630,23 @@ static int init_kernel_tracing(struct ltt_kernel_session *session) { int ret = 0; - if (session->kconsumer_fds_sent == 0) { + if (session->consumer_fds_sent == 0) { /* * Assign default kernel consumer socket if no consumer assigned to the * kernel session. At this point, it's NOT suppose to be 0 but this is * an extra security check. */ if (session->consumer_fd == 0) { - session->consumer_fd = kconsumerd_cmd_sock; + session->consumer_fd = kconsumer_data.cmd_sock; } - ret = send_kconsumerd_fds(session); + ret = send_kconsumer_session_streams(&kconsumer_data, session); if (ret < 0) { ret = LTTCOMM_KERN_CONSUMER_FAIL; goto error; } - session->kconsumer_fds_sent = 1; + session->consumer_fds_sent = 1; } error: @@ -1565,30 +1660,30 @@ static int create_ust_session(struct ltt_session *session, struct lttng_domain *domain) { int ret; - struct ltt_ust_session *lus; - struct ltt_traceable_app *app; + unsigned int uid; + struct ltt_ust_session *lus = NULL; switch (domain->type) { - case LTTNG_DOMAIN_UST_PID: - app = traceable_app_get_by_pid(domain->attr.pid); - if (app == NULL) { - ret = LTTCOMM_APP_NOT_FOUND; - goto error; - } + case LTTNG_DOMAIN_UST: break; default: + ret = LTTCOMM_UNKNOWN_DOMAIN; goto error; } DBG("Creating UST session"); - lus = trace_ust_create_session(session->path, domain->attr.pid, domain); + session_lock_list(); + uid = session_list_ptr->count; + session_unlock_list(); + + lus = trace_ust_create_session(session->path, uid, domain); if (lus == NULL) { ret = LTTCOMM_UST_SESS_FAIL; goto error; } - ret = mkdir_recursive(lus->path, S_IRWXU | S_IRWXG, + ret = mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG, geteuid(), allowed_group()); if (ret < 0) { if (ret != -EEXIST) { @@ -1598,15 +1693,15 @@ static int create_ust_session(struct ltt_session *session, } } - /* Create session on the UST tracer */ - ret = ustctl_create_session(app->sock, lus); - if (ret < 0) { - ret = LTTCOMM_UST_SESS_FAIL; + /* The domain type dictate different actions on session creation */ + switch (domain->type) { + case LTTNG_DOMAIN_UST: + /* No ustctl for the global UST domain */ + break; + default: goto error; } - - cds_list_add(&lus->list, &session->ust_session_list.head); - session->ust_session_list.count++; + session->ust_session = lus; return LTTCOMM_OK; @@ -1631,8 +1726,8 @@ static int create_kernel_session(struct ltt_session *session) } /* Set kernel consumer socket fd */ - if (kconsumerd_cmd_sock) { - session->kernel_session->consumer_fd = kconsumerd_cmd_sock; + if (kconsumer_data.cmd_sock) { + session->kernel_session->consumer_fd = kconsumer_data.cmd_sock; } ret = mkdir_recursive(session->kernel_session->trace_path, @@ -1739,6 +1834,9 @@ static void list_lttng_events(struct ltt_kernel_channel *kchan, case LTTNG_KERNEL_SYSCALL: events[i].type = LTTNG_EVENT_SYSCALL; break; + case LTTNG_KERNEL_ALL: + assert(0); + break; } i++; } @@ -1775,6 +1873,40 @@ error: return ret; } +/* + * Copy channel from attributes and set it in the application channel list. + */ +/* +static int copy_ust_channel_to_app(struct ltt_ust_session *usess, + struct lttng_channel *attr, struct ust_app *app) +{ + int ret; + struct ltt_ust_channel *uchan, *new_chan; + + uchan = trace_ust_get_channel_by_key(usess->channels, attr->name); + if (uchan == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + + new_chan = trace_ust_create_channel(attr, usess->path); + if (new_chan == NULL) { + PERROR("malloc ltt_ust_channel"); + ret = LTTCOMM_FATAL; + goto error; + } + + ret = channel_ust_copy(new_chan, uchan); + if (ret < 0) { + ret = LTTCOMM_FATAL; + goto error; + } + +error: + return ret; +} +*/ + /* * Command LTTNG_ENABLE_CHANNEL processed by the client thread. */ @@ -1782,6 +1914,9 @@ static int cmd_enable_channel(struct ltt_session *session, struct lttng_domain *domain, struct lttng_channel *attr) { int ret; + struct ltt_ust_session *usess = session->ust_session; + + DBG("Enabling channel %s for session %s", session->name, attr->name); switch (domain->type) { case LTTNG_DOMAIN_KERNEL: @@ -1804,12 +1939,44 @@ static int cmd_enable_channel(struct ltt_session *session, kernel_wait_quiescent(kernel_tracer_fd); break; } + case LTTNG_DOMAIN_UST: + { + struct ltt_ust_channel *uchan; + + DBG2("Enabling channel for LTTNG_DOMAIN_UST"); + + /* Get channel in global UST domain HT */ + uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, + attr->name); + if (uchan == NULL) { + uchan = trace_ust_create_channel(attr, usess->pathname); + if (uchan == NULL) { + ret = LTTCOMM_UST_CHAN_FAIL; + goto error; + } + rcu_read_lock(); + hashtable_add_unique(usess->domain_global.channels, &uchan->node); + rcu_read_unlock(); + DBG2("UST channel %s added to global domain HT", attr->name); + } else { + ret = LTTCOMM_UST_CHAN_EXIST; + goto error; + } + + ret = ust_app_add_channel(usess, uchan); + if (ret != LTTCOMM_OK) { + goto error; + } + + break; + } case LTTNG_DOMAIN_UST_PID: { - struct ltt_ust_event *uevent, *new_uevent; + /* + int sock; + struct ltt_ust_channel *uchan; struct ltt_ust_session *usess; - struct ltt_ust_channel *uchan, *app_chan; - struct ltt_traceable_app *app; + struct ust_app *app; usess = trace_ust_get_session_by_pid(&session->ust_session_list, domain->attr.pid); @@ -1818,62 +1985,34 @@ static int cmd_enable_channel(struct ltt_session *session, goto error; } - app = traceable_app_get_by_pid(domain->attr.pid); + app = ust_app_get_by_pid(domain->attr.pid); if (app == NULL) { ret = LTTCOMM_APP_NOT_FOUND; goto error; } + sock = app->sock; uchan = trace_ust_get_channel_by_name(attr->name, usess); if (uchan == NULL) { - ret = channel_ust_create(usess, attr, app->sock); + ret = channel_ust_create(usess, attr, sock); } else { - ret = channel_ust_enable(usess, uchan, app->sock); + ret = channel_ust_enable(usess, uchan, sock); } if (ret != LTTCOMM_OK) { goto error; } - /*TODO: This should be put in an external function */ - - /* Copy UST channel to add to the traceable app */ - uchan = trace_ust_get_channel_by_name(attr->name, usess); - if (uchan == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - - app_chan = trace_ust_create_channel(attr, session->path); - if (app_chan == NULL) { - PERROR("malloc ltt_ust_channel"); - ret = LTTCOMM_FATAL; + ret = copy_ust_channel_to_app(usess, attr, app); + if (ret != LTTCOMM_OK) { goto error; } - memcpy(app_chan, uchan, sizeof(struct ltt_ust_channel)); - CDS_INIT_LIST_HEAD(&app_chan->events.head); - - cds_list_for_each_entry(uevent, &uchan->events.head, list) { - new_uevent = malloc(sizeof(struct ltt_ust_event)); - if (new_uevent == NULL) { - PERROR("malloc ltt_ust_event"); - ret = LTTCOMM_FATAL; - goto error; - } - - memcpy(new_uevent, uevent, sizeof(struct ltt_ust_event)); - cds_list_add(&new_uevent->list, &app_chan->events.head); - app_chan->events.count++; - } - - /* Add channel to traceable_app */ - cds_list_add(&app_chan->list, &app->channels.head); - app->channels.count++; - DBG("UST channel %s created for app sock %d with pid %d", attr->name, app->sock, domain->attr.pid); - break; + */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } default: ret = LTTCOMM_UNKNOWN_DOMAIN; @@ -1893,10 +2032,12 @@ static int cmd_disable_event(struct ltt_session *session, int domain, char *channel_name, char *event_name) { int ret; - struct ltt_kernel_channel *kchan; switch (domain) { case LTTNG_DOMAIN_KERNEL: + { + struct ltt_kernel_channel *kchan; + kchan = trace_kernel_get_channel_by_name(channel_name, session->kernel_session); if (kchan == NULL) { @@ -1904,15 +2045,20 @@ static int cmd_disable_event(struct ltt_session *session, int domain, goto error; } - ret = event_kernel_disable(session->kernel_session, kchan, event_name); + ret = event_kernel_disable_tracepoint(session->kernel_session, kchan, event_name); if (ret != LTTCOMM_OK) { goto error; } kernel_wait_quiescent(kernel_tracer_fd); break; + } + case LTTNG_DOMAIN_UST: + case LTTNG_DOMAIN_UST_EXEC_NAME: + case LTTNG_DOMAIN_UST_PID: + case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: default: - /* TODO: Userspace tracing */ + /* TODO: Other UST domains */ ret = LTTCOMM_NOT_IMPLEMENTED; goto error; } @@ -1976,10 +2122,24 @@ static int cmd_add_context(struct ltt_session *session, int domain, if (ret != LTTCOMM_OK) { goto error; } + break; + case LTTNG_DOMAIN_UST: + { + /* + struct ltt_ust_session *usess; + cds_list_for_each_entry(usess, &session->ust_session_list.head, list) { + ret = context_ust_add(usess, ctx, + event_name, channel_name, domain); + if (ret != LTTCOMM_OK) { + goto error; + } + } break; + */ + } default: - /* TODO: Userspace tracing */ + /* TODO: UST other domains */ ret = LTTCOMM_NOT_IMPLEMENTED; goto error; } @@ -1997,16 +2157,27 @@ static int cmd_enable_event(struct ltt_session *session, int domain, char *channel_name, struct lttng_event *event) { int ret; - struct ltt_kernel_channel *kchan; + struct lttng_channel *attr; + struct ltt_ust_session *usess = session->ust_session; switch (domain) { case LTTNG_DOMAIN_KERNEL: + { + struct ltt_kernel_channel *kchan; + kchan = trace_kernel_get_channel_by_name(channel_name, session->kernel_session); if (kchan == NULL) { + attr = channel_new_default_attr(domain); + if (attr == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + snprintf(attr->name, NAME_MAX, "%s", channel_name); + /* This call will notify the kernel thread */ ret = channel_kernel_create(session->kernel_session, - NULL, kernel_poll_pipe[1]); + attr, kernel_poll_pipe[1]); if (ret != LTTCOMM_OK) { goto error; } @@ -2021,15 +2192,48 @@ static int cmd_enable_event(struct ltt_session *session, int domain, goto error; } - ret = event_kernel_enable(session->kernel_session, kchan, event); + ret = event_kernel_enable_tracepoint(session->kernel_session, kchan, + event); if (ret != LTTCOMM_OK) { goto error; } kernel_wait_quiescent(kernel_tracer_fd); break; + } + case LTTNG_DOMAIN_UST: + { + struct ltt_ust_channel *uchan; + struct ltt_ust_event *uevent; + + uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, + channel_name); + if (uchan == NULL) { + /* TODO: Create default channel */ + ret = LTTCOMM_UST_CHAN_NOT_FOUND; + goto error; + } + + uevent = trace_ust_find_event_by_name(uchan->events, event->name); + if (uevent == NULL) { + uevent = trace_ust_create_event(event); + if (uevent == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + } + + ret = ust_app_add_event(usess, uchan, uevent); + if (ret < 0) { + ret = LTTCOMM_UST_ENABLE_FAIL; + goto error; + } + break; + } + case LTTNG_DOMAIN_UST_EXEC_NAME: + case LTTNG_DOMAIN_UST_PID: + case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: default: - /* TODO: Userspace tracing */ ret = LTTCOMM_NOT_IMPLEMENTED; goto error; } @@ -2071,18 +2275,28 @@ static int cmd_enable_event_all(struct ltt_session *session, int domain, goto error; } - if (event_type == LTTNG_KERNEL_SYSCALL) { - ret = event_kernel_enable_syscalls(session->kernel_session, + switch (event_type) { + case LTTNG_KERNEL_SYSCALL: + ret = event_kernel_enable_all_syscalls(session->kernel_session, kchan, kernel_tracer_fd); - } else { + break; + case LTTNG_KERNEL_TRACEPOINT: /* - * This call enables all LTTNG_KERNEL_TRACEPOINTS and events - * already registered to the channel. + * This call enables all LTTNG_KERNEL_TRACEPOINTS and + * events already registered to the channel. */ + ret = event_kernel_enable_all_tracepoints(session->kernel_session, + kchan, kernel_tracer_fd); + break; + case LTTNG_KERNEL_ALL: + /* Enable syscalls and tracepoints */ ret = event_kernel_enable_all(session->kernel_session, kchan, kernel_tracer_fd); + break; + default: + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; } - if (ret != LTTCOMM_OK) { goto error; } @@ -2136,14 +2350,16 @@ error: static int cmd_start_trace(struct ltt_session *session) { int ret; - struct ltt_kernel_channel *kchan; struct ltt_kernel_session *ksession; + struct ltt_ust_session *usess = session->ust_session; /* Short cut */ ksession = session->kernel_session; /* Kernel tracing */ if (ksession != NULL) { + struct ltt_kernel_channel *kchan; + /* Open kernel metadata */ if (ksession->metadata == NULL) { ret = kernel_open_metadata(ksession, ksession->trace_path); @@ -2194,7 +2410,11 @@ static int cmd_start_trace(struct ltt_session *session) kernel_wait_quiescent(kernel_tracer_fd); } - /* TODO: Start all UST traces */ + ret = ust_app_start_trace(usess); + if (ret < 0) { + ret = LTTCOMM_UST_START_FAIL; + goto error; + } ret = LTTCOMM_OK; @@ -2210,6 +2430,8 @@ static int cmd_stop_trace(struct ltt_session *session) int ret; struct ltt_kernel_channel *kchan; struct ltt_kernel_session *ksession; + //struct ltt_ust_session *usess; + //struct ltt_ust_channel *ustchan; /* Short cut */ ksession = session->kernel_session; @@ -2240,7 +2462,32 @@ static int cmd_stop_trace(struct ltt_session *session) kernel_wait_quiescent(kernel_tracer_fd); } - /* TODO : User-space tracer */ +#ifdef DISABLE + /* Stop each UST session */ + DBG("Stop UST tracing"); + cds_list_for_each_entry(usess, &session->ust_session_list.head, list) { + /* Flush all buffers before stopping */ + ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj); + if (ret < 0) { + ERR("UST metadata flush failed"); + } + + cds_list_for_each_entry(ustchan, &usess->channels.head, list) { + ret = ustctl_flush_buffer(usess->sock, ustchan->obj); + if (ret < 0) { + ERR("UST flush buffer error"); + } + } + + ret = ustctl_stop_session(usess->sock, usess->handle); + if (ret < 0) { + ret = LTTCOMM_KERN_STOP_FAIL; + goto error; + } + + ustctl_wait_quiescent(usess->sock); + } +#endif ret = LTTCOMM_OK; @@ -2285,7 +2532,7 @@ static int cmd_destroy_session(struct ltt_session *session, char *name) perror("write kernel poll pipe"); } - ret = session_destroy(name); + ret = session_destroy(session); return ret; } @@ -2371,7 +2618,7 @@ static ssize_t cmd_list_domains(struct ltt_session *session, nb_dom++; } - nb_dom += session->ust_session_list.count; + /* TODO: User-space tracer domain support */ *domains = malloc(nb_dom * sizeof(struct lttng_domain)); if (*domains == NULL) { @@ -2381,8 +2628,6 @@ static ssize_t cmd_list_domains(struct ltt_session *session, (*domains)[0].type = LTTNG_DOMAIN_KERNEL; - /* TODO: User-space tracer domain support */ - return nb_dom; error: @@ -2410,6 +2655,8 @@ static ssize_t cmd_list_channels(struct ltt_session *session, list_lttng_channels(session, *channels); + /* TODO UST support */ + return nb_chan; error: @@ -2497,7 +2744,9 @@ static int process_client_msg(struct command_ctx *cmd_ctx) break; default: DBG("Getting session %s by name", cmd_ctx->lsm->session.name); + session_lock_list(); cmd_ctx->session = session_find_by_name(cmd_ctx->lsm->session.name); + session_unlock_list(); if (cmd_ctx->session == NULL) { if (cmd_ctx->lsm->session.name != NULL) { ret = LTTCOMM_SESS_NOT_FOUND; @@ -2539,36 +2788,48 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } /* Start the kernel consumer daemon */ - if (kconsumerd_pid == 0 && + pthread_mutex_lock(&kconsumer_data.pid_mutex); + if (kconsumer_data.pid == 0 && cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { - ret = start_kconsumerd(); + pthread_mutex_unlock(&kconsumer_data.pid_mutex); + ret = start_consumerd(&kconsumer_data); if (ret < 0) { ret = LTTCOMM_KERN_CONSUMER_FAIL; goto error; } } + pthread_mutex_unlock(&kconsumer_data.pid_mutex); } break; - case LTTNG_DOMAIN_UST_PID: + case LTTNG_DOMAIN_UST: { - struct ltt_ust_session *usess; - if (need_tracing_session) { - usess = trace_ust_get_session_by_pid( - &cmd_ctx->session->ust_session_list, - cmd_ctx->lsm->domain.attr.pid); - if (usess == NULL) { + if (cmd_ctx->session->ust_session == NULL) { ret = create_ust_session(cmd_ctx->session, &cmd_ctx->lsm->domain); if (ret != LTTCOMM_OK) { goto error; } } + /* Start the kernel consumer daemon */ + pthread_mutex_lock(&ustconsumer_data.pid_mutex); + if (ustconsumer_data.pid == 0 && + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { + pthread_mutex_unlock(&ustconsumer_data.pid_mutex); + ret = start_consumerd(&ustconsumer_data); + if (ret < 0) { + ret = LTTCOMM_KERN_CONSUMER_FAIL; + goto error; + } + + cmd_ctx->session->ust_session->consumer_fd = + ustconsumer_data.cmd_sock; + } + pthread_mutex_unlock(&ustconsumer_data.pid_mutex); } break; } default: - /* TODO Userspace tracer */ break; } @@ -2598,7 +2859,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } case LTTNG_DISABLE_ALL_EVENT: { - DBG("Disabling all kernel event"); + DBG("Disabling all events"); ret = cmd_disable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type, cmd_ctx->lsm->u.disable.channel_name); @@ -2619,7 +2880,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } case LTTNG_ENABLE_ALL_EVENT: { - DBG("Enabling all kernel event"); + DBG("Enabling all events"); ret = cmd_enable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type, cmd_ctx->lsm->u.enable.channel_name, @@ -2826,6 +3087,8 @@ static void *thread_manage_clients(void *data) DBG("[thread] Manage client started"); + rcu_register_thread(); + ret = lttcomm_listen_unix_sock(client_sock); if (ret < 0) { goto error; @@ -2926,6 +3189,7 @@ static void *thread_manage_clients(void *data) // TODO: Validate cmd_ctx including sanity check for // security purpose. + rcu_thread_online(); /* * This function dispatch the work to the kernel or userspace tracer * libs and fill the lttcomm_lttng_msg data structure of all the needed @@ -2933,6 +3197,7 @@ static void *thread_manage_clients(void *data) * everything this function may needs. */ ret = process_client_msg(cmd_ctx); + rcu_thread_offline(); if (ret < 0) { /* * TODO: Inform client somehow of the fatal error. At @@ -2945,7 +3210,7 @@ static void *thread_manage_clients(void *data) DBG("Sending response (size: %d, retcode: %s)", cmd_ctx->lttng_msg_size, - lttng_get_readable_code(-cmd_ctx->llm->ret_code)); + lttng_strerror(-cmd_ctx->llm->ret_code)); ret = send_unix_sock(sock, cmd_ctx->llm, cmd_ctx->lttng_msg_size); if (ret < 0) { ERR("Failed to send data back to client"); @@ -2965,6 +3230,8 @@ error: lttng_poll_clean(&events); clean_command_ctx(&cmd_ctx); + + rcu_unregister_thread(); return NULL; } @@ -2980,13 +3247,15 @@ static void usage(void) fprintf(stderr, " -a, --apps-sock PATH Specify path for apps unix socket\n"); fprintf(stderr, " --kconsumerd-err-sock PATH Specify path for the kernel consumer error socket\n"); fprintf(stderr, " --kconsumerd-cmd-sock PATH Specify path for the kernel consumer command socket\n"); + fprintf(stderr, " --ustconsumerd-err-sock PATH Specify path for the UST consumer error socket\n"); + fprintf(stderr, " --ustconsumerd-cmd-sock PATH Specify path for the UST consumer command socket\n"); fprintf(stderr, " -d, --daemonize Start as a daemon.\n"); fprintf(stderr, " -g, --group NAME Specify the tracing group name. (default: tracing)\n"); fprintf(stderr, " -V, --version Show version number.\n"); fprintf(stderr, " -S, --sig-parent Send SIGCHLD to parent pid to notify readiness.\n"); fprintf(stderr, " -q, --quiet No output at all.\n"); fprintf(stderr, " -v, --verbose Verbose mode. Activate DBG() macro.\n"); - fprintf(stderr, " --verbose-kconsumerd Verbose mode for kconsumerd. Activate DBG() macro.\n"); + fprintf(stderr, " --verbose-consumer Verbose mode for consumer. Activate DBG() macro.\n"); } /* @@ -2999,8 +3268,10 @@ static int parse_args(int argc, char **argv) static struct option long_options[] = { { "client-sock", 1, 0, 'c' }, { "apps-sock", 1, 0, 'a' }, - { "kconsumerd-cmd-sock", 1, 0, 0 }, - { "kconsumerd-err-sock", 1, 0, 0 }, + { "kconsumerd-cmd-sock", 1, 0, 'C' }, + { "kconsumerd-err-sock", 1, 0, 'E' }, + { "ustconsumerd-cmd-sock", 1, 0, 'D' }, + { "ustconsumerd-err-sock", 1, 0, 'F' }, { "daemonize", 0, 0, 'd' }, { "sig-parent", 0, 0, 'S' }, { "help", 0, 0, 'h' }, @@ -3008,13 +3279,13 @@ static int parse_args(int argc, char **argv) { "version", 0, 0, 'V' }, { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, - { "verbose-kconsumerd", 0, 0, 'Z' }, + { "verbose-consumer", 0, 0, 'Z' }, { NULL, 0, 0, 0 } }; while (1) { int option_index = 0; - c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:E:C:Z", + c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:C:E:D:F:Z", long_options, &option_index); if (c == -1) { break; @@ -3049,10 +3320,16 @@ static int parse_args(int argc, char **argv) opt_sig_parent = 1; break; case 'E': - snprintf(kconsumerd_err_unix_sock_path, PATH_MAX, "%s", optarg); + snprintf(kconsumer_data.err_unix_sock_path, PATH_MAX, "%s", optarg); break; case 'C': - snprintf(kconsumerd_cmd_unix_sock_path, PATH_MAX, "%s", optarg); + snprintf(kconsumer_data.cmd_unix_sock_path, PATH_MAX, "%s", optarg); + break; + case 'F': + snprintf(ustconsumer_data.err_unix_sock_path, PATH_MAX, "%s", optarg); + break; + case 'D': + snprintf(ustconsumer_data.cmd_unix_sock_path, PATH_MAX, "%s", optarg); break; case 'q': opt_quiet = 1; @@ -3062,7 +3339,7 @@ static int parse_args(int argc, char **argv) opt_verbose += 1; break; case 'Z': - opt_verbose_kconsumerd += 1; + opt_verbose_consumer += 1; break; default: /* Unknown option or other error. @@ -3180,10 +3457,17 @@ static int set_permissions(void) perror("chown"); } - /* kconsumerd error socket path */ - ret = chown(kconsumerd_err_unix_sock_path, 0, gid); + /* kconsumer error socket path */ + ret = chown(kconsumer_data.err_unix_sock_path, 0, gid); if (ret < 0) { - ERR("Unable to set group on %s", kconsumerd_err_unix_sock_path); + ERR("Unable to set group on %s", kconsumer_data.err_unix_sock_path); + perror("chown"); + } + + /* ustconsumer error socket path */ + ret = chown(ustconsumer_data.err_unix_sock_path, 0, gid); + if (ret < 0) { + ERR("Unable to set group on %s", ustconsumer_data.err_unix_sock_path); perror("chown"); } @@ -3234,43 +3518,49 @@ error: * Setup sockets and directory needed by the kconsumerd communication with the * session daemon. */ -static int set_kconsumerd_sockets(void) +static int set_consumer_sockets(struct consumer_data *consumer_data) { int ret; + const char *path = consumer_data->type == LTTNG_CONSUMER_KERNEL ? + KCONSUMERD_PATH : USTCONSUMERD_PATH; - if (strlen(kconsumerd_err_unix_sock_path) == 0) { - snprintf(kconsumerd_err_unix_sock_path, PATH_MAX, - KCONSUMERD_ERR_SOCK_PATH); + if (strlen(consumer_data->err_unix_sock_path) == 0) { + snprintf(consumer_data->err_unix_sock_path, PATH_MAX, + consumer_data->type == LTTNG_CONSUMER_KERNEL ? + KCONSUMERD_ERR_SOCK_PATH : + USTCONSUMERD_ERR_SOCK_PATH); } - if (strlen(kconsumerd_cmd_unix_sock_path) == 0) { - snprintf(kconsumerd_cmd_unix_sock_path, PATH_MAX, - KCONSUMERD_CMD_SOCK_PATH); + if (strlen(consumer_data->cmd_unix_sock_path) == 0) { + snprintf(consumer_data->cmd_unix_sock_path, PATH_MAX, + consumer_data->type == LTTNG_CONSUMER_KERNEL ? + KCONSUMERD_CMD_SOCK_PATH : + USTCONSUMERD_CMD_SOCK_PATH); } - ret = mkdir(KCONSUMERD_PATH, S_IRWXU | S_IRWXG); + ret = mkdir(path, S_IRWXU | S_IRWXG); if (ret < 0) { if (errno != EEXIST) { - ERR("Failed to create " KCONSUMERD_PATH); + ERR("Failed to create %s", path); goto error; } ret = 0; } /* Create the kconsumerd error unix socket */ - kconsumerd_err_sock = - lttcomm_create_unix_sock(kconsumerd_err_unix_sock_path); - if (kconsumerd_err_sock < 0) { - ERR("Create unix sock failed: %s", kconsumerd_err_unix_sock_path); + consumer_data->err_sock = + lttcomm_create_unix_sock(consumer_data->err_unix_sock_path); + if (consumer_data->err_sock < 0) { + ERR("Create unix sock failed: %s", consumer_data->err_unix_sock_path); ret = -1; goto error; } /* File permission MUST be 660 */ - ret = chmod(kconsumerd_err_unix_sock_path, + ret = chmod(consumer_data->err_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (ret < 0) { - ERR("Set file permissions failed: %s", kconsumerd_err_unix_sock_path); + ERR("Set file permissions failed: %s", consumer_data->err_unix_sock_path); perror("chmod"); goto error; } @@ -3370,6 +3660,8 @@ int main(int argc, char **argv) void *status; const char *home_path; + rcu_register_thread(); + /* Create thread quit pipe */ if ((ret = init_thread_quit_pipe()) < 0) { goto error; @@ -3465,11 +3757,15 @@ int main(int argc, char **argv) * kernel tracer. */ if (is_root) { - ret = set_kconsumerd_sockets(); + ret = set_consumer_sockets(&kconsumer_data); if (ret < 0) { goto exit; } + ret = set_consumer_sockets(&ustconsumer_data); + if (ret < 0) { + goto exit; + } /* Setup kernel tracer */ init_kernel_tracer(); @@ -3509,6 +3805,9 @@ int main(int argc, char **argv) /* Init UST command queue. */ cds_wfq_init(&ust_cmd_queue.queue); + /* Init UST app hash table */ + ust_app_ht_alloc(); + /* * Get session list pointer. This pointer MUST NOT be free(). This list is * statically declared in session.c @@ -3592,9 +3891,9 @@ exit_dispatch: goto error; /* join error, exit without cleanup */ } - ret = join_kconsumerd_thread(); + ret = join_consumer_thread(&kconsumer_data); if (ret != 0) { - perror("join_kconsumerd"); + perror("join_consumer"); goto error; /* join error, exit without cleanup */ } @@ -3603,7 +3902,10 @@ exit: /* * cleanup() is called when no other thread is running. */ + rcu_thread_online(); cleanup(); + rcu_thread_offline(); + rcu_unregister_thread(); if (!ret) exit(EXIT_SUCCESS); error: