X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=0e20b4f67886dc656e88e5631cce8fc223379205;hp=f6d560c3325fe376a74c084b29b9d195396b1b62;hb=1400a85d14101d8ed140f44011a183f6b5b80d29;hpb=139ac87245fd1ca18d60a0efca32b50e4c1d8730 diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index f6d560c33..0e20b4f67 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -48,6 +47,7 @@ #include "lttng-sessiond.h" #include "channel.h" +#include "cmd.h" #include "consumer.h" #include "context.h" #include "event.h" @@ -61,6 +61,7 @@ #include "fd-limit.h" #include "filter.h" #include "health.h" +#include "testpoint.h" #define CONSUMERD_FILE "lttng-consumerd" @@ -80,13 +81,20 @@ 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 char *rundir; -/* Consumer daemon specific control data */ +/* + * Consumer daemon specific control data. Every value not initialized here is + * set to 0 by the static definition. + */ static struct consumer_data kconsumer_data = { .type = LTTNG_CONSUMER_KERNEL, .err_unix_sock_path = DEFAULT_KCONSUMERD_ERR_SOCK_PATH, .cmd_unix_sock_path = DEFAULT_KCONSUMERD_CMD_SOCK_PATH, .err_sock = -1, .cmd_sock = -1, + .pid_mutex = PTHREAD_MUTEX_INITIALIZER, + .lock = PTHREAD_MUTEX_INITIALIZER, + .cond = PTHREAD_COND_INITIALIZER, + .cond_mutex = PTHREAD_MUTEX_INITIALIZER, }; static struct consumer_data ustconsumer64_data = { .type = LTTNG_CONSUMER64_UST, @@ -94,6 +102,10 @@ static struct consumer_data ustconsumer64_data = { .cmd_unix_sock_path = DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH, .err_sock = -1, .cmd_sock = -1, + .pid_mutex = PTHREAD_MUTEX_INITIALIZER, + .lock = PTHREAD_MUTEX_INITIALIZER, + .cond = PTHREAD_COND_INITIALIZER, + .cond_mutex = PTHREAD_MUTEX_INITIALIZER, }; static struct consumer_data ustconsumer32_data = { .type = LTTNG_CONSUMER32_UST, @@ -101,6 +113,10 @@ static struct consumer_data ustconsumer32_data = { .cmd_unix_sock_path = DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH, .err_sock = -1, .cmd_sock = -1, + .pid_mutex = PTHREAD_MUTEX_INITIALIZER, + .lock = PTHREAD_MUTEX_INITIALIZER, + .cond = PTHREAD_COND_INITIALIZER, + .cond_mutex = PTHREAD_MUTEX_INITIALIZER, }; /* Shared between threads */ @@ -118,7 +134,7 @@ static char health_unix_sock_path[PATH_MAX]; /* Sockets and FDs */ static int client_sock = -1; static int apps_sock = -1; -static int kernel_tracer_fd = -1; +int kernel_tracer_fd = -1; static int kernel_poll_pipe[2] = { -1, -1 }; /* @@ -170,6 +186,8 @@ static const char *consumerd64_bin = CONFIG_CONSUMERD64_BIN; static const char *consumerd32_libdir = CONFIG_CONSUMERD32_LIBDIR; static const char *consumerd64_libdir = CONFIG_CONSUMERD64_LIBDIR; +static const char *module_proc_lttng = "/proc/lttng"; + /* * Consumer daemon state which is changed when spawning it, killing it or in * case of a fatal error. @@ -204,16 +222,6 @@ enum consumerd_state { static enum consumerd_state ust_consumerd_state; static enum consumerd_state kernel_consumerd_state; -/* - * Used to keep a unique index for each relayd socket created where this value - * is associated with streams on the consumer so it can match the right relayd - * to send to. - * - * This value should be incremented atomically for safety purposes and future - * possible concurrent access. - */ -static unsigned int relayd_net_seq_idx; - /* Used for the health monitoring of the session daemon. See health.h */ struct health_state health_thread_cmd; struct health_state health_thread_app_manage; @@ -359,54 +367,6 @@ error: return ret; } -/* - * Complete teardown of a kernel session. This free all data structure related - * to a kernel session and update counter. - */ -static void teardown_kernel_session(struct ltt_session *session) -{ - if (!session->kernel_session) { - DBG3("No kernel session when tearing down session"); - return; - } - - DBG("Tearing down kernel session"); - - /* - * If a custom kernel consumer was registered, close the socket before - * tearing down the complete kernel session structure - */ - if (kconsumer_data.cmd_sock >= 0 && - session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) { - lttcomm_close_unix_sock(session->kernel_session->consumer_fd); - } - - trace_kernel_destroy_session(session->kernel_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) -{ - int ret; - - if (!session->ust_session) { - DBG3("No UST session when tearing down session"); - return; - } - - DBG("Tearing down UST session(s)"); - - ret = ust_app_destroy_trace_all(session->ust_session); - if (ret) { - ERR("Error in ust_app_destroy_trace_all"); - } - - trace_ust_destroy_session(session->ust_session); -} - /* * Stop all threads by closing the thread quit pipe. */ @@ -437,6 +397,9 @@ static void cleanup(void) DBG("Cleaning up"); + /* First thing first, stop all threads */ + utils_close_pipe(thread_quit_pipe); + DBG("Removing %s directory", rundir); ret = asprintf(&cmd, "rm -rf %s", rundir); if (ret < 0) { @@ -459,17 +422,13 @@ static void cleanup(void) /* Cleanup ALL session */ cds_list_for_each_entry_safe(sess, stmp, &session_list_ptr->head, list) { - teardown_kernel_session(sess); - teardown_ust_session(sess); - free(sess); + cmd_destroy_session(sess, kernel_poll_pipe[1]); } } DBG("Closing all UST sockets"); ust_app_clean_list(); - pthread_mutex_destroy(&kconsumer_data.pid_mutex); - if (is_root && !opt_no_kernel) { DBG2("Closing kernel fd"); if (kernel_tracer_fd >= 0) { @@ -481,8 +440,8 @@ static void cleanup(void) DBG("Unloading kernel modules"); modprobe_remove_lttng_all(); } + utils_close_pipe(kernel_poll_pipe); - utils_close_pipe(thread_quit_pipe); utils_close_pipe(apps_cmd_pipe); /* */ @@ -634,6 +593,7 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd) { int ret = 0; struct ltt_session *session; + struct ltt_kernel_session *ksess; struct ltt_kernel_channel *channel; DBG("Updating kernel streams for channel fd %d", fd); @@ -645,14 +605,9 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd) session_unlock(session); continue; } + ksess = session->kernel_session; - /* This is not suppose to be -1 but this is an extra security check */ - if (session->kernel_session->consumer_fd < 0) { - session->kernel_session->consumer_fd = consumer_data->cmd_sock; - } - - cds_list_for_each_entry(channel, - &session->kernel_session->channel_list.head, list) { + cds_list_for_each_entry(channel, &ksess->channel_list.head, list) { if (channel->fd == fd) { DBG("Channel found, updating kernel streams"); ret = kernel_open_channel_stream(channel); @@ -665,13 +620,23 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd) * that tracing is started so it is safe to send our updated * stream fds. */ - if (session->kernel_session->consumer_fds_sent == 1 && - session->kernel_session->consumer != NULL) { - ret = kernel_consumer_send_channel_stream( - session->kernel_session->consumer_fd, channel, - session->kernel_session); - if (ret < 0) { - goto error; + if (ksess->consumer_fds_sent == 1 && ksess->consumer != NULL) { + struct lttng_ht_iter iter; + struct consumer_socket *socket; + + + cds_lfht_for_each_entry(ksess->consumer->socks->ht, + &iter.iter, socket, node.node) { + /* Code flow error */ + assert(socket->fd >= 0); + + pthread_mutex_lock(socket->lock); + ret = kernel_consumer_send_channel_stream(socket->fd, + channel, ksess); + pthread_mutex_unlock(socket->lock); + if (ret < 0) { + goto error; + } } } goto error; @@ -724,8 +689,12 @@ static void *thread_manage_kernel(void *data) DBG("Thread manage kernel started"); + testpoint(thread_manage_kernel); + health_code_update(&health_thread_kernel); + testpoint(thread_manage_kernel_before_loop); + ret = create_thread_poll_set(&events, 2); if (ret < 0) { goto error_poll_create; @@ -832,6 +801,29 @@ error_poll_create: return NULL; } +/* + * Signal pthread condition of the consumer data that the thread. + */ +static void signal_consumer_condition(struct consumer_data *data, int state) +{ + pthread_mutex_lock(&data->cond_mutex); + + /* + * The state is set before signaling. It can be any value, it's the waiter + * job to correctly interpret this condition variable associated to the + * consumer pthread_cond. + * + * A value of 0 means that the corresponding thread of the consumer data + * was not started. 1 indicates that the thread has started and is ready + * for action. A negative value means that there was an error during the + * thread bootstrap. + */ + data->consumer_thread_is_ready = state; + (void) pthread_cond_signal(&data->cond); + + pthread_mutex_unlock(&data->cond_mutex); +} + /* * This thread manage the consumer error sent back to the session daemon. */ @@ -873,6 +865,9 @@ static void *thread_manage_consumer(void *data) /* Inifinite blocking call, waiting for transmission */ restart: health_poll_update(&consumer_data->health); + + testpoint(thread_manage_consumer); + ret = lttng_poll_wait(&events, -1); health_poll_update(&consumer_data->health); if (ret < 0) { @@ -926,17 +921,17 @@ restart: health_code_update(&consumer_data->health); - if (code == CONSUMERD_COMMAND_SOCK_READY) { + if (code == LTTCOMM_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); + /* On error, signal condition and quit. */ + signal_consumer_condition(consumer_data, -1); PERROR("consumer connect"); goto error; } - /* Signal condition to tell that the kconsumerd is ready */ - sem_post(&consumer_data->sem); - DBG("consumer command socket ready"); + signal_consumer_condition(consumer_data, 1); + DBG("Consumer command socket ready"); } else { ERR("consumer error when waiting for SOCK_READY : %s", lttcomm_get_readable_code(-code)); @@ -1070,6 +1065,8 @@ static void *thread_manage_apps(void *data) DBG("[thread] Manage application started"); + testpoint(thread_manage_apps); + rcu_register_thread(); rcu_thread_online(); @@ -1085,6 +1082,8 @@ static void *thread_manage_apps(void *data) goto error; } + testpoint(thread_manage_apps_before_loop); + health_code_update(&health_thread_app_manage); while (1) { @@ -1308,6 +1307,8 @@ static void *thread_registration_apps(void *data) DBG("[thread] Manage application registration started"); + testpoint(thread_registration_apps); + ret = lttcomm_listen_unix_sock(apps_sock); if (ret < 0) { goto error_listen; @@ -1490,59 +1491,110 @@ error_create_poll: */ static int spawn_consumer_thread(struct consumer_data *consumer_data) { - int ret; + int ret, clock_ret; struct timespec timeout; - timeout.tv_sec = DEFAULT_SEM_WAIT_TIMEOUT; - timeout.tv_nsec = 0; + /* Make sure we set the readiness flag to 0 because we are NOT ready */ + consumer_data->consumer_thread_is_ready = 0; - /* Setup semaphore */ - ret = sem_init(&consumer_data->sem, 0, 0); - if (ret < 0) { - PERROR("sem_init consumer semaphore"); + /* Setup pthread condition */ + ret = pthread_condattr_init(&consumer_data->condattr); + if (ret != 0) { + errno = ret; + PERROR("pthread_condattr_init consumer data"); + goto error; + } + + /* + * Set the monotonic clock in order to make sure we DO NOT jump in time + * between the clock_gettime() call and the timedwait call. See bug #324 + * for a more details and how we noticed it. + */ + ret = pthread_condattr_setclock(&consumer_data->condattr, CLOCK_MONOTONIC); + if (ret != 0) { + errno = ret; + PERROR("pthread_condattr_setclock consumer data"); + goto error; + } + + ret = pthread_cond_init(&consumer_data->cond, &consumer_data->condattr); + if (ret != 0) { + errno = ret; + PERROR("pthread_cond_init consumer data"); goto error; } - ret = pthread_create(&consumer_data->thread, NULL, - thread_manage_consumer, consumer_data); + ret = pthread_create(&consumer_data->thread, NULL, thread_manage_consumer, + consumer_data); if (ret != 0) { PERROR("pthread_create consumer"); ret = -1; goto error; } + /* We are about to wait on a pthread condition */ + pthread_mutex_lock(&consumer_data->cond_mutex); + /* 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); + clock_ret = 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 + * increment the timeout too many times. + */ + timeout.tv_sec += DEFAULT_SEM_WAIT_TIMEOUT; + + /* + * The following loop COULD be skipped in some conditions so this is why we + * set ret to 0 in order to make sure at least one round of the loop is + * done. + */ + ret = 0; + + /* + * Loop until the condition is reached or when a timeout is reached. Note + * that the pthread_cond_timedwait(P) man page specifies that EINTR can NOT + * be returned but the pthread_cond(3), from the glibc-doc, says that it is + * possible. This loop does not take any chances and works with both of + * them. + */ + while (!consumer_data->consumer_thread_is_ready && ret != ETIMEDOUT) { + if (clock_ret < 0) { + PERROR("clock_gettime spawn consumer"); + /* Infinite wait for the consumerd thread to be ready */ + ret = pthread_cond_wait(&consumer_data->cond, + &consumer_data->cond_mutex); + } else { + ret = pthread_cond_timedwait(&consumer_data->cond, + &consumer_data->cond_mutex, &timeout); + } } - if (ret < 0) { - if (errno == ETIMEDOUT) { + /* Release the pthread condition */ + pthread_mutex_unlock(&consumer_data->cond_mutex); + + if (ret != 0) { + errno = ret; + if (ret == ETIMEDOUT) { /* * Call has timed out so we kill the kconsumerd_thread and return * an error. */ - ERR("The consumer thread was never ready. Killing it"); + ERR("Condition timed out. 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"); + PERROR("pthread_cond_wait failed consumer thread"); } goto error; } pthread_mutex_lock(&consumer_data->pid_mutex); if (consumer_data->pid == 0) { - ERR("Kconsumerd did not start"); + ERR("Consumerd did not start"); pthread_mutex_unlock(&consumer_data->pid_mutex); goto error; } @@ -1562,7 +1614,8 @@ static int join_consumer_thread(struct consumer_data *consumer_data) void *status; int ret; - if (consumer_data->pid != 0) { + /* Consumer pid must be a real one. */ + if (consumer_data->pid > 0) { ret = kill(consumer_data->pid, SIGTERM); if (ret) { ERR("Error killing consumer daemon"); @@ -1792,14 +1845,6 @@ static int check_consumer_health(void) return ret; } -/* - * Check version of the lttng-modules. - */ -static int validate_lttng_modules_version(void) -{ - return kernel_validate_version(kernel_tracer_fd); -} - /* * Setup necessary data for kernel tracer action. */ @@ -1822,7 +1867,7 @@ static int init_kernel_tracer(void) } /* Validate kernel version */ - ret = validate_lttng_modules_version(); + ret = kernel_validate_version(kernel_tracer_fd); if (ret < 0) { goto error_version; } @@ -1842,7 +1887,7 @@ error_version: PERROR("close"); } kernel_tracer_fd = -1; - return LTTCOMM_KERN_VERSION; + return LTTNG_ERR_KERN_VERSION; error_modules: ret = close(kernel_tracer_fd); @@ -1857,244 +1902,12 @@ error: WARN("No kernel tracer available"); kernel_tracer_fd = -1; if (!is_root) { - return LTTCOMM_NEED_ROOT_SESSIOND; - } else { - return LTTCOMM_KERN_NA; - } -} - -/* - * Init tracing by creating trace directory and sending fds kernel consumer. - */ -static int init_kernel_tracing(struct ltt_kernel_session *session) -{ - int ret = 0; - - if (session->consumer_fds_sent == 0 && session->consumer != NULL) { - /* - * Assign default kernel consumer socket if no consumer assigned to the - * kernel session. At this point, it's NOT supposed to be -1 but this is - * an extra security check. - */ - if (session->consumer_fd < 0) { - session->consumer_fd = kconsumer_data.cmd_sock; - } - - ret = kernel_consumer_send_session(session->consumer_fd, session); - if (ret < 0) { - ret = LTTCOMM_KERN_CONSUMER_FAIL; - goto error; - } - } - -error: - return ret; -} - -/* - * Create a socket to the relayd using the URI. - * - * On success, the relayd_sock pointer is set to the created socket. - * Else, it is untouched and an lttcomm error code is returned. - */ -static int create_connect_relayd(struct consumer_output *output, - const char *session_name, struct lttng_uri *uri, - struct lttcomm_sock **relayd_sock) -{ - int ret; - struct lttcomm_sock *sock; - - /* Create socket object from URI */ - sock = lttcomm_alloc_sock_from_uri(uri); - if (sock == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - - ret = lttcomm_create_sock(sock); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - - /* Connect to relayd so we can proceed with a session creation. */ - ret = relayd_connect(sock); - if (ret < 0) { - ERR("Unable to reach lttng-relayd"); - ret = LTTCOMM_RELAYD_SESSION_FAIL; - goto free_sock; - } - - /* Create socket for control stream. */ - if (uri->stype == LTTNG_STREAM_CONTROL) { - DBG3("Creating relayd stream socket from URI"); - - /* Check relayd version */ - ret = relayd_version_check(sock, LTTNG_UST_COMM_MAJOR, 0); - if (ret < 0) { - ret = LTTCOMM_RELAYD_VERSION_FAIL; - goto close_sock; - } - } else if (uri->stype == LTTNG_STREAM_DATA) { - DBG3("Creating relayd data socket from URI"); + return LTTNG_ERR_NEED_ROOT_SESSIOND; } else { - /* Command is not valid */ - ERR("Relayd invalid stream type: %d", uri->stype); - ret = LTTCOMM_INVALID; - goto close_sock; - } - - *relayd_sock = sock; - - return LTTCOMM_OK; - -close_sock: - if (sock) { - (void) relayd_close(sock); - } -free_sock: - if (sock) { - lttcomm_destroy_sock(sock); - } -error: - return ret; -} - -/* - * Connect to the relayd using URI and send the socket to the right consumer. - */ -static int send_socket_relayd_consumer(int domain, struct ltt_session *session, - struct lttng_uri *relayd_uri, struct consumer_output *consumer, - int consumer_fd) -{ - int ret; - struct lttcomm_sock *sock = NULL; - - /* Set the network sequence index if not set. */ - if (consumer->net_seq_index == -1) { - /* - * Increment net_seq_idx because we are about to transfer the - * new relayd socket to the consumer. - */ - uatomic_inc(&relayd_net_seq_idx); - /* Assign unique key so the consumer can match streams */ - consumer->net_seq_index = uatomic_read(&relayd_net_seq_idx); - } - - /* Connect to relayd and make version check if uri is the control. */ - ret = create_connect_relayd(consumer, session->name, relayd_uri, &sock); - if (ret != LTTCOMM_OK) { - goto close_sock; - } - - /* If the control socket is connected, network session is ready */ - if (relayd_uri->stype == LTTNG_STREAM_CONTROL) { - session->net_handle = 1; - } - - /* Send relayd socket to consumer. */ - ret = consumer_send_relayd_socket(consumer_fd, sock, - consumer, relayd_uri->stype); - if (ret < 0) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - goto close_sock; - } - - ret = LTTCOMM_OK; - - /* - * Close socket which was dup on the consumer side. The session daemon does - * NOT keep track of the relayd socket(s) once transfer to the consumer. - */ - -close_sock: - if (sock) { - (void) relayd_close(sock); - lttcomm_destroy_sock(sock); + return LTTNG_ERR_KERN_NA; } - - return ret; -} - -/* - * Send both relayd sockets to a specific consumer and domain. This is a - * helper function to facilitate sending the information to the consumer for a - * session. - */ -static int send_sockets_relayd_consumer(int domain, - struct ltt_session *session, struct consumer_output *consumer, int fd) -{ - int ret; - - /* Sending control relayd socket. */ - ret = send_socket_relayd_consumer(domain, session, - &consumer->dst.net.control, consumer, fd); - if (ret != LTTCOMM_OK) { - goto error; - } - - /* Sending data relayd socket. */ - ret = send_socket_relayd_consumer(domain, session, - &consumer->dst.net.data, consumer, fd); - if (ret != LTTCOMM_OK) { - goto error; - } - -error: - return ret; } -/* - * Setup relayd connections for a tracing session. First creates the socket to - * the relayd and send them to the right domain consumer. Consumer type MUST be - * network. - */ -static int setup_relayd(struct ltt_session *session) -{ - int ret = LTTCOMM_OK; - struct ltt_ust_session *usess; - struct ltt_kernel_session *ksess; - - assert(session); - - usess = session->ust_session; - ksess = session->kernel_session; - - DBG2("Setting relayd for session %s", session->name); - - if (usess && usess->consumer->sock == -1 && - usess->consumer->type == CONSUMER_DST_NET && - usess->consumer->enabled) { - /* Setup relayd for 64 bits consumer */ - if (ust_consumerd64_fd >= 0) { - send_sockets_relayd_consumer(LTTNG_DOMAIN_UST, session, - usess->consumer, ust_consumerd64_fd); - if (ret != LTTCOMM_OK) { - goto error; - } - } - - /* Setup relayd for 32 bits consumer */ - if (ust_consumerd32_fd >= 0) { - send_sockets_relayd_consumer(LTTNG_DOMAIN_UST, session, - usess->consumer, ust_consumerd32_fd); - if (ret != LTTCOMM_OK) { - goto error; - } - } - } else if (ksess && ksess->consumer->sock == -1 && - ksess->consumer->type == CONSUMER_DST_NET && - ksess->consumer->enabled) { - send_sockets_relayd_consumer(LTTNG_DOMAIN_KERNEL, session, - ksess->consumer, ksess->consumer_fd); - if (ret != LTTCOMM_OK) { - goto error; - } - } - -error: - return ret; -} /* * Copy consumer output from the tracing session to the domain session. The @@ -2107,9 +1920,21 @@ static int copy_session_consumer(int domain, struct ltt_session *session) const char *dir_name; struct consumer_output *consumer; + assert(session); + assert(session->consumer); + switch (domain) { case LTTNG_DOMAIN_KERNEL: DBG3("Copying tracing session consumer output in kernel session"); + /* + * XXX: We should audit the session creation and what this function + * does "extra" in order to avoid a destroy since this function is used + * in the domain session creation (kernel and ust) only. Same for UST + * domain. + */ + if (session->kernel_session->consumer) { + consumer_destroy_output(session->kernel_session->consumer); + } session->kernel_session->consumer = consumer_copy_output(session->consumer); /* Ease our life a bit for the next part */ @@ -2118,6 +1943,9 @@ static int copy_session_consumer(int domain, struct ltt_session *session) break; case LTTNG_DOMAIN_UST: DBG3("Copying tracing session consumer output in UST session"); + if (session->ust_session->consumer) { + consumer_destroy_output(session->ust_session->consumer); + } session->ust_session->consumer = consumer_copy_output(session->consumer); /* Ease our life a bit for the next part */ @@ -2125,21 +1953,16 @@ static int copy_session_consumer(int domain, struct ltt_session *session) dir_name = DEFAULT_UST_TRACE_DIR; break; default: - ret = LTTCOMM_UNKNOWN_DOMAIN; + ret = LTTNG_ERR_UNKNOWN_DOMAIN; goto error; } /* Append correct directory to subdir */ - strncat(consumer->subdir, dir_name, sizeof(consumer->subdir)); + strncat(consumer->subdir, dir_name, + sizeof(consumer->subdir) - strlen(consumer->subdir) - 1); DBG3("Copy session consumer subdir %s", consumer->subdir); - /* Add default trace directory name */ - if (consumer->type == CONSUMER_DST_LOCAL) { - strncat(consumer->dst.trace_path, dir_name, - sizeof(consumer->dst.trace_path)); - } - - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: return ret; @@ -2155,6 +1978,7 @@ static int create_ust_session(struct ltt_session *session, struct ltt_ust_session *lus = NULL; assert(session); + assert(domain); assert(session->consumer); switch (domain->type) { @@ -2162,7 +1986,7 @@ static int create_ust_session(struct ltt_session *session, break; default: ERR("Unknown UST domain on create session %d", domain->type); - ret = LTTCOMM_UNKNOWN_DOMAIN; + ret = LTTNG_ERR_UNKNOWN_DOMAIN; goto error; } @@ -2170,33 +1994,21 @@ static int create_ust_session(struct ltt_session *session, lus = trace_ust_create_session(session->path, session->id, domain); if (lus == NULL) { - ret = LTTCOMM_UST_SESS_FAIL; + ret = LTTNG_ERR_UST_SESS_FAIL; goto error; } - if (session->consumer->type == CONSUMER_DST_LOCAL) { - ret = run_as_mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG, - session->uid, session->gid); - if (ret < 0) { - if (ret != -EEXIST) { - ERR("Trace directory creation error"); - ret = LTTCOMM_UST_SESS_FAIL; - goto error; - } - } - } - lus->uid = session->uid; lus->gid = session->gid; session->ust_session = lus; /* Copy session output to the newly created UST session */ ret = copy_session_consumer(domain->type, session); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto error; } - return LTTCOMM_OK; + return LTTNG_OK; error: free(lus); @@ -2215,23 +2027,22 @@ static int create_kernel_session(struct ltt_session *session) ret = kernel_create_session(session, kernel_tracer_fd); if (ret < 0) { - ret = LTTCOMM_KERN_SESS_FAIL; + ret = LTTNG_ERR_KERN_SESS_FAIL; goto error; } - /* Set kernel consumer socket fd */ - if (kconsumer_data.cmd_sock >= 0) { - session->kernel_session->consumer_fd = kconsumer_data.cmd_sock; - } + /* Code flow safety */ + assert(session->kernel_session); /* Copy session output to the newly created Kernel session */ ret = copy_session_consumer(LTTNG_DOMAIN_KERNEL, session); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto error; } /* Create directory(ies) on local filesystem. */ - if (session->consumer->type == CONSUMER_DST_LOCAL) { + if (session->kernel_session->consumer->type == CONSUMER_DST_LOCAL && + strlen(session->kernel_session->consumer->dst.trace_path) > 0) { ret = run_as_mkdir_recursive( session->kernel_session->consumer->dst.trace_path, S_IRWXU | S_IRWXG, session->uid, session->gid); @@ -2246,7 +2057,7 @@ static int create_kernel_session(struct ltt_session *session) session->kernel_session->uid = session->uid; session->kernel_session->gid = session->gid; - return LTTCOMM_OK; + return LTTNG_OK; error: trace_kernel_destroy_session(session->kernel_session); @@ -2254,19 +2065,6 @@ error: return ret; } -/* - * Check if the UID or GID match the session. Root user has access to all - * sessions. - */ -static int session_access_ok(struct ltt_session *session, uid_t uid, gid_t gid) -{ - if (uid != session->uid && gid != session->gid && uid != 0) { - return 0; - } else { - return 1; - } -} - /* * Count number of session permitted by uid/gid. */ @@ -2276,7 +2074,7 @@ static unsigned int lttng_sessions_count(uid_t uid, gid_t gid) struct ltt_session *session; DBG("Counting number of available session for UID %d GID %d", - uid, gid); + uid, gid); cds_list_for_each_entry(session, &session_list_ptr->head, list) { /* * Only list the sessions the user can control. @@ -2290,1795 +2088,20 @@ static unsigned int lttng_sessions_count(uid_t uid, gid_t gid) } /* - * Using the session list, filled a lttng_session array to send back to the - * client for session listing. + * Process the command requested by the lttng client within the command + * context structure. This function make sure that the return structure (llm) + * is set and ready for transmission before returning. + * + * Return any error encountered or 0 for success. * - * The session list lock MUST be acquired before calling this function. Use - * session_lock_list() and session_unlock_list(). + * "sock" is only used for special-case var. len data. */ -static void list_lttng_sessions(struct lttng_session *sessions, uid_t uid, - gid_t gid) +static int process_client_msg(struct command_ctx *cmd_ctx, int sock, + int *sock_error) { - unsigned int i = 0; - struct ltt_session *session; - - DBG("Getting all available session for UID %d GID %d", - uid, gid); - /* - * Iterate over session list and append data after the control struct in - * the buffer. - */ - cds_list_for_each_entry(session, &session_list_ptr->head, list) { - /* - * Only list the sessions the user can control. - */ - if (!session_access_ok(session, uid, gid)) { - continue; - } - strncpy(sessions[i].path, session->path, PATH_MAX); - sessions[i].path[PATH_MAX - 1] = '\0'; - strncpy(sessions[i].name, session->name, NAME_MAX); - sessions[i].name[NAME_MAX - 1] = '\0'; - sessions[i].enabled = session->enabled; - i++; - } -} - -/* - * Fill lttng_channel array of all channels. - */ -static void list_lttng_channels(int domain, struct ltt_session *session, - struct lttng_channel *channels) -{ - int i = 0; - struct ltt_kernel_channel *kchan; - - DBG("Listing channels for session %s", session->name); - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - /* Kernel channels */ - if (session->kernel_session != NULL) { - cds_list_for_each_entry(kchan, - &session->kernel_session->channel_list.head, list) { - /* Copy lttng_channel struct to array */ - memcpy(&channels[i], kchan->channel, sizeof(struct lttng_channel)); - channels[i].enabled = kchan->enabled; - i++; - } - } - break; - case LTTNG_DOMAIN_UST: - { - struct lttng_ht_iter iter; - struct ltt_ust_channel *uchan; - - cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, - &iter.iter, uchan, node.node) { - strncpy(channels[i].name, uchan->name, LTTNG_SYMBOL_NAME_LEN); - channels[i].attr.overwrite = uchan->attr.overwrite; - channels[i].attr.subbuf_size = uchan->attr.subbuf_size; - channels[i].attr.num_subbuf = uchan->attr.num_subbuf; - channels[i].attr.switch_timer_interval = - uchan->attr.switch_timer_interval; - channels[i].attr.read_timer_interval = - uchan->attr.read_timer_interval; - channels[i].enabled = uchan->enabled; - switch (uchan->attr.output) { - case LTTNG_UST_MMAP: - default: - channels[i].attr.output = LTTNG_EVENT_MMAP; - break; - } - i++; - } - break; - } - default: - break; - } -} - -/* - * Create a list of ust global domain events. - */ -static int list_lttng_ust_global_events(char *channel_name, - struct ltt_ust_domain_global *ust_global, struct lttng_event **events) -{ - int i = 0, ret = 0; - unsigned int nb_event = 0; - struct lttng_ht_iter iter; - struct lttng_ht_node_str *node; - struct ltt_ust_channel *uchan; - struct ltt_ust_event *uevent; - struct lttng_event *tmp; - - DBG("Listing UST global events for channel %s", channel_name); - - rcu_read_lock(); - - lttng_ht_lookup(ust_global->channels, (void *)channel_name, &iter); - node = lttng_ht_iter_get_node_str(&iter); - if (node == NULL) { - ret = -LTTCOMM_UST_CHAN_NOT_FOUND; - goto error; - } - - uchan = caa_container_of(&node->node, struct ltt_ust_channel, node.node); - - nb_event += lttng_ht_get_count(uchan->events); - - if (nb_event == 0) { - ret = nb_event; - goto error; - } - - DBG3("Listing UST global %d events", nb_event); - - tmp = zmalloc(nb_event * sizeof(struct lttng_event)); - if (tmp == NULL) { - ret = -LTTCOMM_FATAL; - goto error; - } - - cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) { - strncpy(tmp[i].name, uevent->attr.name, LTTNG_SYMBOL_NAME_LEN); - tmp[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; - tmp[i].enabled = uevent->enabled; - switch (uevent->attr.instrumentation) { - case LTTNG_UST_TRACEPOINT: - tmp[i].type = LTTNG_EVENT_TRACEPOINT; - break; - case LTTNG_UST_PROBE: - tmp[i].type = LTTNG_EVENT_PROBE; - break; - case LTTNG_UST_FUNCTION: - tmp[i].type = LTTNG_EVENT_FUNCTION; - break; - } - tmp[i].loglevel = uevent->attr.loglevel; - switch (uevent->attr.loglevel_type) { - case LTTNG_UST_LOGLEVEL_ALL: - tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; - break; - case LTTNG_UST_LOGLEVEL_RANGE: - tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE; - break; - case LTTNG_UST_LOGLEVEL_SINGLE: - tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE; - break; - } - if (uevent->filter) { - tmp[i].filter = 1; - } - i++; - } - - ret = nb_event; - *events = tmp; - -error: - rcu_read_unlock(); - return ret; -} - -/* - * Fill lttng_event array of all kernel events in the channel. - */ -static int list_lttng_kernel_events(char *channel_name, - struct ltt_kernel_session *kernel_session, struct lttng_event **events) -{ - int i = 0, ret; - unsigned int nb_event; - struct ltt_kernel_event *event; - struct ltt_kernel_channel *kchan; - - kchan = trace_kernel_get_channel_by_name(channel_name, kernel_session); - if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } - - nb_event = kchan->event_count; - - DBG("Listing events for channel %s", kchan->channel->name); - - if (nb_event == 0) { - ret = nb_event; - goto error; - } - - *events = zmalloc(nb_event * sizeof(struct lttng_event)); - if (*events == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - - /* Kernel channels */ - cds_list_for_each_entry(event, &kchan->events_list.head , list) { - strncpy((*events)[i].name, event->event->name, LTTNG_SYMBOL_NAME_LEN); - (*events)[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; - (*events)[i].enabled = event->enabled; - switch (event->event->instrumentation) { - case LTTNG_KERNEL_TRACEPOINT: - (*events)[i].type = LTTNG_EVENT_TRACEPOINT; - break; - case LTTNG_KERNEL_KPROBE: - case LTTNG_KERNEL_KRETPROBE: - (*events)[i].type = LTTNG_EVENT_PROBE; - memcpy(&(*events)[i].attr.probe, &event->event->u.kprobe, - sizeof(struct lttng_kernel_kprobe)); - break; - case LTTNG_KERNEL_FUNCTION: - (*events)[i].type = LTTNG_EVENT_FUNCTION; - memcpy(&((*events)[i].attr.ftrace), &event->event->u.ftrace, - sizeof(struct lttng_kernel_function)); - break; - case LTTNG_KERNEL_NOOP: - (*events)[i].type = LTTNG_EVENT_NOOP; - break; - case LTTNG_KERNEL_SYSCALL: - (*events)[i].type = LTTNG_EVENT_SYSCALL; - break; - case LTTNG_KERNEL_ALL: - assert(0); - break; - } - i++; - } - - return nb_event; - -error: - return ret; -} - -/* - * Command LTTNG_DISABLE_CHANNEL processed by the client thread. - */ -static int cmd_disable_channel(struct ltt_session *session, - int domain, char *channel_name) -{ - int ret; - struct ltt_ust_session *usess; - - usess = session->ust_session; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - ret = channel_kernel_disable(session->kernel_session, - channel_name); - if (ret != LTTCOMM_OK) { - goto error; - } - - kernel_wait_quiescent(kernel_tracer_fd); - break; - } - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_channel *uchan; - struct lttng_ht *chan_ht; - - chan_ht = usess->domain_global.channels; - - uchan = trace_ust_find_channel_by_name(chan_ht, channel_name); - if (uchan == NULL) { - ret = LTTCOMM_UST_CHAN_NOT_FOUND; - goto error; - } - - ret = channel_ust_disable(usess, domain, uchan); - if (ret != LTTCOMM_OK) { - goto error; - } - break; - } -#if 0 - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: -#endif - default: - ret = LTTCOMM_UNKNOWN_DOMAIN; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_ENABLE_CHANNEL processed by the client thread. - */ -static int cmd_enable_channel(struct ltt_session *session, - int domain, struct lttng_channel *attr) -{ - int ret; - struct ltt_ust_session *usess = session->ust_session; - struct lttng_ht *chan_ht; - - DBG("Enabling channel %s for session %s", attr->name, session->name); - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - struct ltt_kernel_channel *kchan; - - kchan = trace_kernel_get_channel_by_name(attr->name, - session->kernel_session); - if (kchan == NULL) { - ret = channel_kernel_create(session->kernel_session, - attr, kernel_poll_pipe[1]); - } else { - ret = channel_kernel_enable(session->kernel_session, kchan); - } - - if (ret != LTTCOMM_OK) { - goto error; - } - - kernel_wait_quiescent(kernel_tracer_fd); - break; - } - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_channel *uchan; - - chan_ht = usess->domain_global.channels; - - uchan = trace_ust_find_channel_by_name(chan_ht, attr->name); - if (uchan == NULL) { - ret = channel_ust_create(usess, domain, attr); - } else { - ret = channel_ust_enable(usess, domain, uchan); - } - break; - } -#if 0 - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: -#endif - default: - ret = LTTCOMM_UNKNOWN_DOMAIN; - goto error; - } - -error: - return ret; -} - -/* - * Command LTTNG_DISABLE_EVENT processed by the client thread. - */ -static int cmd_disable_event(struct ltt_session *session, int domain, - char *channel_name, char *event_name) -{ - int ret; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - struct ltt_kernel_channel *kchan; - struct ltt_kernel_session *ksess; - - ksess = session->kernel_session; - - kchan = trace_kernel_get_channel_by_name(channel_name, ksess); - if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } - - ret = event_kernel_disable_tracepoint(ksess, kchan, event_name); - 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_session *usess; - - usess = session->ust_session; - - uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, - channel_name); - if (uchan == NULL) { - ret = LTTCOMM_UST_CHAN_NOT_FOUND; - goto error; - } - - ret = event_ust_disable_tracepoint(usess, domain, uchan, event_name); - if (ret != LTTCOMM_OK) { - goto error; - } - - DBG3("Disable UST event %s in channel %s completed", event_name, - channel_name); - break; - } -#if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: -#endif - default: - ret = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_DISABLE_ALL_EVENT processed by the client thread. - */ -static int cmd_disable_event_all(struct ltt_session *session, int domain, - char *channel_name) -{ - int ret; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - struct ltt_kernel_session *ksess; - struct ltt_kernel_channel *kchan; - - ksess = session->kernel_session; - - kchan = trace_kernel_get_channel_by_name(channel_name, ksess); - if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } - - ret = event_kernel_disable_all(ksess, kchan); - if (ret != LTTCOMM_OK) { - goto error; - } - - kernel_wait_quiescent(kernel_tracer_fd); - break; - } - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *usess; - struct ltt_ust_channel *uchan; - - usess = session->ust_session; - - uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, - channel_name); - if (uchan == NULL) { - ret = LTTCOMM_UST_CHAN_NOT_FOUND; - goto error; - } - - ret = event_ust_disable_all_tracepoints(usess, domain, uchan); - if (ret != 0) { - goto error; - } - - DBG3("Disable all UST events in channel %s completed", channel_name); - - break; - } -#if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: -#endif - default: - ret = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_ADD_CONTEXT processed by the client thread. - */ -static int cmd_add_context(struct ltt_session *session, int domain, - char *channel_name, char *event_name, struct lttng_event_context *ctx) -{ - int ret; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - /* Add kernel context to kernel tracer */ - ret = context_kernel_add(session->kernel_session, ctx, - event_name, channel_name); - if (ret != LTTCOMM_OK) { - goto error; - } - break; - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *usess = session->ust_session; - - ret = context_ust_add(usess, domain, ctx, event_name, channel_name); - if (ret != LTTCOMM_OK) { - goto error; - } - break; - } -#if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: -#endif - default: - ret = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_SET_FILTER processed by the client thread. - */ -static int cmd_set_filter(struct ltt_session *session, int domain, - char *channel_name, char *event_name, - struct lttng_filter_bytecode *bytecode) -{ - int ret; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - ret = LTTCOMM_FATAL; - break; - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *usess = session->ust_session; - - ret = filter_ust_set(usess, domain, bytecode, event_name, channel_name); - if (ret != LTTCOMM_OK) { - goto error; - } - break; - } -#if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: -#endif - default: - ret = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; - -} - -/* - * Command LTTNG_ENABLE_EVENT processed by the client thread. - */ -static int cmd_enable_event(struct ltt_session *session, int domain, - char *channel_name, struct lttng_event *event) -{ - int ret; - 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, - attr, kernel_poll_pipe[1]); - if (ret != LTTCOMM_OK) { - free(attr); - goto error; - } - free(attr); - } - - /* Get the newly created kernel channel pointer */ - kchan = trace_kernel_get_channel_by_name(channel_name, - session->kernel_session); - if (kchan == NULL) { - /* This sould not happen... */ - ret = LTTCOMM_FATAL; - goto error; - } - - 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 lttng_channel *attr; - struct ltt_ust_channel *uchan; - - /* Get channel from global UST domain */ - uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, - channel_name); - if (uchan == NULL) { - /* Create default channel */ - attr = channel_new_default_attr(domain); - if (attr == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - snprintf(attr->name, NAME_MAX, "%s", channel_name); - attr->name[NAME_MAX - 1] = '\0'; - - ret = channel_ust_create(usess, domain, attr); - if (ret != LTTCOMM_OK) { - free(attr); - goto error; - } - free(attr); - - /* Get the newly created channel reference back */ - uchan = trace_ust_find_channel_by_name( - usess->domain_global.channels, channel_name); - if (uchan == NULL) { - /* Something is really wrong */ - ret = LTTCOMM_FATAL; - goto error; - } - } - - /* At this point, the session and channel exist on the tracer */ - ret = event_ust_enable_tracepoint(usess, domain, uchan, event); - if (ret != LTTCOMM_OK) { - goto error; - } - break; - } -#if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: -#endif - default: - ret = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_ENABLE_ALL_EVENT processed by the client thread. - */ -static int cmd_enable_event_all(struct ltt_session *session, int domain, - char *channel_name, int event_type) -{ - int ret; - struct ltt_kernel_channel *kchan; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - kchan = trace_kernel_get_channel_by_name(channel_name, - session->kernel_session); - if (kchan == NULL) { - /* This call will notify the kernel thread */ - ret = channel_kernel_create(session->kernel_session, NULL, - kernel_poll_pipe[1]); - if (ret != LTTCOMM_OK) { - goto error; - } - - /* Get the newly created kernel channel pointer */ - kchan = trace_kernel_get_channel_by_name(channel_name, - session->kernel_session); - if (kchan == NULL) { - /* This sould not happen... */ - ret = LTTCOMM_FATAL; - goto error; - } - - } - - switch (event_type) { - case LTTNG_EVENT_SYSCALL: - ret = event_kernel_enable_all_syscalls(session->kernel_session, - kchan, kernel_tracer_fd); - break; - case LTTNG_EVENT_TRACEPOINT: - /* - * 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_EVENT_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; - } - - /* Manage return value */ - if (ret != LTTCOMM_OK) { - goto error; - } - - kernel_wait_quiescent(kernel_tracer_fd); - break; - case LTTNG_DOMAIN_UST: - { - struct lttng_channel *attr; - struct ltt_ust_channel *uchan; - struct ltt_ust_session *usess = session->ust_session; - - /* Get channel from global UST domain */ - uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, - channel_name); - if (uchan == NULL) { - /* Create default channel */ - attr = channel_new_default_attr(domain); - if (attr == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - snprintf(attr->name, NAME_MAX, "%s", channel_name); - attr->name[NAME_MAX - 1] = '\0'; - - /* Use the internal command enable channel */ - ret = channel_ust_create(usess, domain, attr); - if (ret != LTTCOMM_OK) { - free(attr); - goto error; - } - free(attr); - - /* Get the newly created channel reference back */ - uchan = trace_ust_find_channel_by_name( - usess->domain_global.channels, channel_name); - if (uchan == NULL) { - /* Something is really wrong */ - ret = LTTCOMM_FATAL; - goto error; - } - } - - /* At this point, the session and channel exist on the tracer */ - - switch (event_type) { - case LTTNG_EVENT_ALL: - case LTTNG_EVENT_TRACEPOINT: - ret = event_ust_enable_all_tracepoints(usess, domain, uchan); - if (ret != LTTCOMM_OK) { - goto error; - } - break; - default: - ret = LTTCOMM_UST_ENABLE_FAIL; - goto error; - } - - /* Manage return value */ - if (ret != LTTCOMM_OK) { - goto error; - } - - break; - } -#if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: -#endif - default: - ret = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_LIST_TRACEPOINTS processed by the client thread. - */ -static ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events) -{ - int ret; - ssize_t nb_events = 0; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - nb_events = kernel_list_events(kernel_tracer_fd, events); - if (nb_events < 0) { - ret = LTTCOMM_KERN_LIST_FAIL; - goto error; - } - break; - case LTTNG_DOMAIN_UST: - nb_events = ust_app_list_events(events); - if (nb_events < 0) { - ret = LTTCOMM_UST_LIST_FAIL; - goto error; - } - break; - default: - ret = LTTCOMM_UND; - goto error; - } - - return nb_events; - -error: - /* Return negative value to differentiate return code */ - return -ret; -} - -/* - * Command LTTNG_LIST_TRACEPOINT_FIELDS processed by the client thread. - */ -static ssize_t cmd_list_tracepoint_fields(int domain, - struct lttng_event_field **fields) -{ - int ret; - ssize_t nb_fields = 0; - - switch (domain) { - case LTTNG_DOMAIN_UST: - nb_fields = ust_app_list_event_fields(fields); - if (nb_fields < 0) { - ret = LTTCOMM_UST_LIST_FAIL; - goto error; - } - break; - case LTTNG_DOMAIN_KERNEL: - default: /* fall-through */ - ret = LTTCOMM_UND; - goto error; - } - - return nb_fields; - -error: - /* Return negative value to differentiate return code */ - return -ret; -} - -/* - * Command LTTNG_START_TRACE processed by the client thread. - */ -static int cmd_start_trace(struct ltt_session *session) -{ - int ret; - struct ltt_kernel_session *ksession; - struct ltt_ust_session *usess; - struct ltt_kernel_channel *kchan; - - /* Ease our life a bit ;) */ - ksession = session->kernel_session; - usess = session->ust_session; - - if (session->enabled) { - /* Already started. */ - ret = LTTCOMM_TRACE_ALREADY_STARTED; - goto error; - } - - session->enabled = 1; - - ret = setup_relayd(session); - if (ret != LTTCOMM_OK) { - ERR("Error setting up relayd for session %s", session->name); - goto error; - } - - /* Kernel tracing */ - if (ksession != NULL) { - /* Open kernel metadata */ - if (ksession->metadata == NULL) { - ret = kernel_open_metadata(ksession, - ksession->consumer->dst.trace_path); - if (ret < 0) { - ret = LTTCOMM_KERN_META_FAIL; - goto error; - } - } - - /* Open kernel metadata stream */ - if (ksession->metadata_stream_fd < 0) { - ret = kernel_open_metadata_stream(ksession); - if (ret < 0) { - ERR("Kernel create metadata stream failed"); - ret = LTTCOMM_KERN_STREAM_FAIL; - goto error; - } - } - - /* For each channel */ - cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) { - if (kchan->stream_count == 0) { - ret = kernel_open_channel_stream(kchan); - if (ret < 0) { - ret = LTTCOMM_KERN_STREAM_FAIL; - goto error; - } - /* Update the stream global counter */ - ksession->stream_count_global += ret; - } - } - - /* Setup kernel consumer socket and send fds to it */ - ret = init_kernel_tracing(ksession); - if (ret < 0) { - ret = LTTCOMM_KERN_START_FAIL; - goto error; - } - - /* This start the kernel tracing */ - ret = kernel_start_session(ksession); - if (ret < 0) { - ret = LTTCOMM_KERN_START_FAIL; - goto error; - } - - /* Quiescent wait after starting trace */ - kernel_wait_quiescent(kernel_tracer_fd); - } - - /* Flag session that trace should start automatically */ - if (usess) { - usess->start_trace = 1; - - ret = ust_app_start_trace_all(usess); - if (ret < 0) { - ret = LTTCOMM_UST_START_FAIL; - goto error; - } - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_STOP_TRACE processed by the client thread. - */ -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; - - /* Short cut */ - ksession = session->kernel_session; - usess = session->ust_session; - - if (!session->enabled) { - ret = LTTCOMM_TRACE_ALREADY_STOPPED; - goto error; - } - - session->enabled = 0; - - /* Kernel tracer */ - if (ksession != NULL) { - DBG("Stop kernel tracing"); - - /* Flush metadata if exist */ - if (ksession->metadata_stream_fd >= 0) { - ret = kernel_metadata_flush_buffer(ksession->metadata_stream_fd); - if (ret < 0) { - ERR("Kernel metadata flush failed"); - } - } - - /* Flush all buffers before stopping */ - cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) { - ret = kernel_flush_buffer(kchan); - if (ret < 0) { - ERR("Kernel flush buffer error"); - } - } - - ret = kernel_stop_session(ksession); - if (ret < 0) { - ret = LTTCOMM_KERN_STOP_FAIL; - goto error; - } - - kernel_wait_quiescent(kernel_tracer_fd); - } - - if (usess) { - usess->start_trace = 0; - - ret = ust_app_stop_trace_all(usess); - if (ret < 0) { - ret = LTTCOMM_UST_STOP_FAIL; - goto error; - } - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_CREATE_SESSION_URI processed by the client thread. - */ -static int cmd_create_session_uri(char *name, struct lttng_uri *ctrl_uri, - struct lttng_uri *data_uri, unsigned int enable_consumer, - lttng_sock_cred *creds) -{ - int ret; - char *path = NULL; - struct ltt_session *session; - struct consumer_output *consumer; - - /* Verify if the session already exist */ - session = session_find_by_name(name); - if (session != NULL) { - ret = LTTCOMM_EXIST_SESS; - goto error; - } - - /* TODO: validate URIs */ - - /* Create default consumer output */ - consumer = consumer_create_output(CONSUMER_DST_LOCAL); - if (consumer == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - strncpy(consumer->subdir, ctrl_uri->subdir, sizeof(consumer->subdir)); - DBG2("Consumer subdir set to %s", consumer->subdir); - - switch (ctrl_uri->dtype) { - case LTTNG_DST_IPV4: - case LTTNG_DST_IPV6: - /* Set control URI into consumer output object */ - ret = consumer_set_network_uri(consumer, ctrl_uri); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - - /* Set data URI into consumer output object */ - ret = consumer_set_network_uri(consumer, data_uri); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - - /* Empty path since the session is network */ - path = ""; - break; - case LTTNG_DST_PATH: - /* Very volatile pointer. Only used for the create session. */ - path = ctrl_uri->dst.path; - strncpy(consumer->dst.trace_path, path, - sizeof(consumer->dst.trace_path)); - break; - } - - /* Set if the consumer is enabled or not */ - consumer->enabled = enable_consumer; - - ret = session_create(name, path, LTTNG_SOCK_GET_UID_CRED(creds), - LTTNG_SOCK_GET_GID_CRED(creds)); - if (ret != LTTCOMM_OK) { - goto consumer_error; - } - - /* Get the newly created session pointer back */ - session = session_find_by_name(name); - assert(session); - - /* Assign consumer to session */ - session->consumer = consumer; - - return LTTCOMM_OK; - -consumer_error: - consumer_destroy_output(consumer); -error: - return ret; -} - -/* - * Command LTTNG_CREATE_SESSION processed by the client thread. - */ -static int cmd_create_session(char *name, char *path, lttng_sock_cred *creds) -{ - int ret; - struct lttng_uri uri; - - /* Zeroed temporary URI */ - memset(&uri, 0, sizeof(uri)); - - uri.dtype = LTTNG_DST_PATH; - uri.utype = LTTNG_URI_DST; - strncpy(uri.dst.path, path, sizeof(uri.dst.path)); - - /* TODO: Strip date-time from path and put it in uri's subdir */ - - ret = cmd_create_session_uri(name, &uri, NULL, 1, creds); - if (ret != LTTCOMM_OK) { - goto error; - } - -error: - return ret; -} - -/* - * Command LTTNG_DESTROY_SESSION processed by the client thread. - */ -static int cmd_destroy_session(struct ltt_session *session, char *name) -{ - int ret; - - /* Clean kernel session teardown */ - teardown_kernel_session(session); - /* UST session teardown */ - teardown_ust_session(session); - - /* - * Must notify the kernel thread here to update it's poll setin order - * to remove the channel(s)' fd just destroyed. - */ - ret = notify_thread_pipe(kernel_poll_pipe[1]); - if (ret < 0) { - PERROR("write kernel poll pipe"); - } - - ret = session_destroy(session); - - return ret; -} - -/* - * Command LTTNG_CALIBRATE processed by the client thread. - */ -static int cmd_calibrate(int domain, struct lttng_calibrate *calibrate) -{ - int ret; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - struct lttng_kernel_calibrate kcalibrate; - - kcalibrate.type = calibrate->type; - ret = kernel_calibrate(kernel_tracer_fd, &kcalibrate); - if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; - goto error; - } - break; - } - case LTTNG_DOMAIN_UST: - { - struct lttng_ust_calibrate ucalibrate; - - ucalibrate.type = calibrate->type; - ret = ust_app_calibrate_glb(&ucalibrate); - if (ret < 0) { - ret = LTTCOMM_UST_CALIBRATE_FAIL; - goto error; - } - break; - } - default: - ret = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_REGISTER_CONSUMER processed by the client thread. - */ -static int cmd_register_consumer(struct ltt_session *session, int domain, - char *sock_path) -{ - int ret, sock; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - /* Can't register a consumer if there is already one */ - if (session->kernel_session->consumer_fds_sent != 0) { - ret = LTTCOMM_KERN_CONSUMER_FAIL; - goto error; - } - - sock = lttcomm_connect_unix_sock(sock_path); - if (sock < 0) { - ret = LTTCOMM_CONNECT_FAIL; - goto error; - } - - session->kernel_session->consumer_fd = sock; - break; - default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_LIST_DOMAINS processed by the client thread. - */ -static ssize_t cmd_list_domains(struct ltt_session *session, - struct lttng_domain **domains) -{ - int ret, index = 0; - ssize_t nb_dom = 0; - - if (session->kernel_session != NULL) { - DBG3("Listing domains found kernel domain"); - nb_dom++; - } - - if (session->ust_session != NULL) { - DBG3("Listing domains found UST global domain"); - nb_dom++; - } - - *domains = zmalloc(nb_dom * sizeof(struct lttng_domain)); - if (*domains == NULL) { - ret = -LTTCOMM_FATAL; - goto error; - } - - if (session->kernel_session != NULL) { - (*domains)[index].type = LTTNG_DOMAIN_KERNEL; - index++; - } - - if (session->ust_session != NULL) { - (*domains)[index].type = LTTNG_DOMAIN_UST; - index++; - } - - return nb_dom; - -error: - return ret; -} - -/* - * Command LTTNG_LIST_CHANNELS processed by the client thread. - */ -static ssize_t cmd_list_channels(int domain, struct ltt_session *session, - struct lttng_channel **channels) -{ - int ret; - ssize_t nb_chan = 0; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - if (session->kernel_session != NULL) { - nb_chan = session->kernel_session->channel_count; - } - DBG3("Number of kernel channels %zd", nb_chan); - break; - case LTTNG_DOMAIN_UST: - if (session->ust_session != NULL) { - nb_chan = lttng_ht_get_count( - session->ust_session->domain_global.channels); - } - DBG3("Number of UST global channels %zd", nb_chan); - break; - default: - *channels = NULL; - ret = -LTTCOMM_UND; - goto error; - } - - if (nb_chan > 0) { - *channels = zmalloc(nb_chan * sizeof(struct lttng_channel)); - if (*channels == NULL) { - ret = -LTTCOMM_FATAL; - goto error; - } - - list_lttng_channels(domain, session, *channels); - } else { - *channels = NULL; - } - - return nb_chan; - -error: - return ret; -} - -/* - * Command LTTNG_LIST_EVENTS processed by the client thread. - */ -static ssize_t cmd_list_events(int domain, struct ltt_session *session, - char *channel_name, struct lttng_event **events) -{ - int ret = 0; - ssize_t nb_event = 0; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - if (session->kernel_session != NULL) { - nb_event = list_lttng_kernel_events(channel_name, - session->kernel_session, events); - } - break; - case LTTNG_DOMAIN_UST: - { - if (session->ust_session != NULL) { - nb_event = list_lttng_ust_global_events(channel_name, - &session->ust_session->domain_global, events); - } - break; - } - default: - ret = -LTTCOMM_UND; - goto error; - } - - ret = nb_event; - -error: - return ret; -} - -/* - * Command LTTNG_SET_CONSUMER_URI processed by the client thread. - */ -static int cmd_set_consumer_uri(int domain, struct ltt_session *session, - struct lttng_uri *uri) -{ - int ret; - struct ltt_kernel_session *ksess = session->kernel_session; - struct ltt_ust_session *usess = session->ust_session; - struct consumer_output *consumer; - - /* Can't enable consumer after session started. */ - if (session->enabled) { - ret = LTTCOMM_TRACE_ALREADY_STARTED; - goto error; - } - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - /* Code flow error if we don't have a kernel session here. */ - assert(ksess); - - /* Create consumer output if none exists */ - consumer = ksess->tmp_consumer; - if (consumer == NULL) { - consumer = consumer_copy_output(ksess->consumer); - if (consumer == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - /* Reassign new pointer */ - ksess->tmp_consumer = consumer; - } - - switch (uri->dtype) { - case LTTNG_DST_IPV4: - case LTTNG_DST_IPV6: - DBG2("Setting network URI for kernel session %s", session->name); - - /* Set URI into consumer output object */ - ret = consumer_set_network_uri(consumer, uri); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - - /* On a new subdir, reappend the default trace dir. */ - if (strlen(uri->subdir) != 0) { - strncat(consumer->subdir, DEFAULT_KERNEL_TRACE_DIR, - sizeof(consumer->subdir)); - } - - ret = send_socket_relayd_consumer(domain, session, uri, consumer, - ksess->consumer_fd); - if (ret != LTTCOMM_OK) { - goto error; - } - break; - case LTTNG_DST_PATH: - DBG2("Setting trace directory path from URI to %s", uri->dst.path); - memset(consumer->dst.trace_path, 0, - sizeof(consumer->dst.trace_path)); - strncpy(consumer->dst.trace_path, uri->dst.path, - sizeof(consumer->dst.trace_path)); - /* Append default kernel trace dir */ - strncat(consumer->dst.trace_path, DEFAULT_KERNEL_TRACE_DIR, - sizeof(consumer->dst.trace_path)); - break; - } - - /* All good! */ - break; - case LTTNG_DOMAIN_UST: - /* Code flow error if we don't have a kernel session here. */ - assert(usess); - - /* Create consumer output if none exists */ - consumer = usess->tmp_consumer; - if (consumer == NULL) { - consumer = consumer_copy_output(usess->consumer); - if (consumer == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - /* Reassign new pointer */ - usess->tmp_consumer = consumer; - } - - switch (uri->dtype) { - case LTTNG_DST_IPV4: - case LTTNG_DST_IPV6: - { - DBG2("Setting network URI for UST session %s", session->name); - - /* Set URI into consumer object */ - ret = consumer_set_network_uri(consumer, uri); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - - /* On a new subdir, reappend the default trace dir. */ - if (strlen(uri->subdir) != 0) { - strncat(consumer->subdir, DEFAULT_UST_TRACE_DIR, - sizeof(consumer->subdir)); - } - - if (ust_consumerd64_fd >= 0) { - ret = send_socket_relayd_consumer(domain, session, uri, - consumer, ust_consumerd64_fd); - if (ret != LTTCOMM_OK) { - goto error; - } - } - - if (ust_consumerd32_fd >= 0) { - ret = send_socket_relayd_consumer(domain, session, uri, - consumer, ust_consumerd32_fd); - if (ret != LTTCOMM_OK) { - goto error; - } - } - - break; - } - case LTTNG_DST_PATH: - DBG2("Setting trace directory path from URI to %s", uri->dst.path); - memset(consumer->dst.trace_path, 0, - sizeof(consumer->dst.trace_path)); - strncpy(consumer->dst.trace_path, uri->dst.path, - sizeof(consumer->dst.trace_path)); - /* Append default UST trace dir */ - strncat(consumer->dst.trace_path, DEFAULT_UST_TRACE_DIR, - sizeof(consumer->dst.trace_path)); - break; - } - break; - } - - /* All good! */ - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_DISABLE_CONSUMER processed by the client thread. - */ -static int cmd_disable_consumer(int domain, struct ltt_session *session) -{ - int ret; - struct ltt_kernel_session *ksess = session->kernel_session; - struct ltt_ust_session *usess = session->ust_session; - struct consumer_output *consumer; - - if (session->enabled) { - /* Can't disable consumer on an already started session */ - ret = LTTCOMM_TRACE_ALREADY_STARTED; - goto error; - } - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - /* Code flow error if we don't have a kernel session here. */ - assert(ksess); - - DBG("Disabling kernel consumer"); - consumer = ksess->consumer; - - break; - case LTTNG_DOMAIN_UST: - /* Code flow error if we don't have a UST session here. */ - assert(usess); - - DBG("Disabling UST consumer"); - consumer = usess->consumer; - - break; - default: - ret = LTTCOMM_UNKNOWN_DOMAIN; - goto error; - } - - assert(consumer); - consumer->enabled = 0; - - /* Success at this point */ - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_ENABLE_CONSUMER processed by the client thread. - */ -static int cmd_enable_consumer(int domain, struct ltt_session *session) -{ - int ret; - struct ltt_kernel_session *ksess = session->kernel_session; - struct ltt_ust_session *usess = session->ust_session; - struct consumer_output *tmp_out; - - /* Can't enable consumer after session started. */ - if (session->enabled) { - ret = LTTCOMM_TRACE_ALREADY_STARTED; - goto error; - } - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - /* Code flow error if we don't have a kernel session here. */ - assert(ksess); - - /* - * Check if we have already sent fds to the consumer. In that case, - * the enable-consumer command can't be used because a start trace - * had previously occured. - */ - if (ksess->consumer_fds_sent) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - goto error; - } - - tmp_out = ksess->tmp_consumer; - if (tmp_out == NULL) { - /* No temp. consumer output exists. Using the current one. */ - DBG3("No temporary consumer. Using default"); - ret = LTTCOMM_OK; - goto error; - } - - switch (tmp_out->type) { - case CONSUMER_DST_LOCAL: - DBG2("Consumer output is local. Creating directory(ies)"); - - /* Create directory(ies) */ - ret = run_as_mkdir_recursive(tmp_out->dst.trace_path, - S_IRWXU | S_IRWXG, session->uid, session->gid); - if (ret < 0) { - if (ret != -EEXIST) { - ERR("Trace directory creation error"); - ret = LTTCOMM_FATAL; - goto error; - } - } - break; - case CONSUMER_DST_NET: - DBG2("Consumer output is network. Validating URIs"); - /* Validate if we have both control and data path set. */ - if (!tmp_out->dst.net.control_isset) { - ret = LTTCOMM_URI_CTRL_MISS; - goto error; - } - - if (!tmp_out->dst.net.data_isset) { - ret = LTTCOMM_URI_DATA_MISS; - goto error; - } - - /* Check established network session state */ - if (session->net_handle == 0) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - ERR("Session network handle is not set on enable-consumer"); - goto error; - } - - /* Append default kernel trace dir to subdir */ - strncat(ksess->consumer->subdir, DEFAULT_KERNEL_TRACE_DIR, - sizeof(ksess->consumer->subdir)); - - break; - } - - /* - * @session-lock - * This is race free for now since the session lock is acquired before - * ending up in this function. No other threads can access this kernel - * session without this lock hence freeing the consumer output object - * is valid. - */ - consumer_destroy_output(ksess->consumer); - ksess->consumer = tmp_out; - ksess->tmp_consumer = NULL; - - break; - case LTTNG_DOMAIN_UST: - /* Code flow error if we don't have a UST session here. */ - assert(usess); - - /* - * Check if we have already sent fds to the consumer. In that case, - * the enable-consumer command can't be used because a start trace - * had previously occured. - */ - if (usess->start_trace) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - goto error; - } - - tmp_out = usess->tmp_consumer; - if (tmp_out == NULL) { - /* No temp. consumer output exists. Using the current one. */ - DBG3("No temporary consumer. Using default"); - ret = LTTCOMM_OK; - goto error; - } - - switch (tmp_out->type) { - case CONSUMER_DST_LOCAL: - DBG2("Consumer output is local. Creating directory(ies)"); - - /* Create directory(ies) */ - ret = run_as_mkdir_recursive(tmp_out->dst.trace_path, - S_IRWXU | S_IRWXG, session->uid, session->gid); - if (ret < 0) { - if (ret != -EEXIST) { - ERR("Trace directory creation error"); - ret = LTTCOMM_FATAL; - goto error; - } - } - break; - case CONSUMER_DST_NET: - DBG2("Consumer output is network. Validating URIs"); - /* Validate if we have both control and data path set. */ - if (!tmp_out->dst.net.control_isset) { - ret = LTTCOMM_URI_CTRL_MISS; - goto error; - } - - if (!tmp_out->dst.net.data_isset) { - ret = LTTCOMM_URI_DATA_MISS; - goto error; - } - - /* Check established network session state */ - if (session->net_handle == 0) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - DBG2("Session network handle is not set on enable-consumer"); - goto error; - } - - if (tmp_out->net_seq_index == -1) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - DBG2("Network index is not set on the consumer"); - goto error; - } - - /* Append default kernel trace dir to subdir */ - strncat(usess->consumer->subdir, DEFAULT_UST_TRACE_DIR, - sizeof(usess->consumer->subdir)); - - break; - } - - /* - * @session-lock - * This is race free for now since the session lock is acquired before - * ending up in this function. No other threads can access this kernel - * session without this lock hence freeing the consumer output object - * is valid. - */ - consumer_destroy_output(usess->consumer); - usess->consumer = tmp_out; - usess->tmp_consumer = NULL; - - break; - } - - /* Success at this point */ - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Process the command requested by the lttng client within the command - * context structure. This function make sure that the return structure (llm) - * is set and ready for transmission before returning. - * - * Return any error encountered or 0 for success. - * - * "sock" is only used for special-case var. len data. - */ -static int process_client_msg(struct command_ctx *cmd_ctx, int sock, - int *sock_error) -{ - int ret = LTTCOMM_OK; - int need_tracing_session = 1; - int need_domain; + int ret = LTTNG_OK; + int need_tracing_session = 1; + int need_domain; DBG("Processing client command %d", cmd_ctx->lsm->cmd_type); @@ -4086,12 +2109,12 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, switch (cmd_ctx->lsm->cmd_type) { case LTTNG_CREATE_SESSION: - case LTTNG_CREATE_SESSION_URI: case LTTNG_DESTROY_SESSION: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_DOMAINS: case LTTNG_START_TRACE: case LTTNG_STOP_TRACE: + case LTTNG_DATA_AVAILABLE: need_domain = 0; break; default: @@ -4101,13 +2124,24 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, if (opt_no_kernel && need_domain && cmd_ctx->lsm->domain.type == LTTNG_DOMAIN_KERNEL) { if (!is_root) { - ret = LTTCOMM_NEED_ROOT_SESSIOND; + ret = LTTNG_ERR_NEED_ROOT_SESSIOND; } else { - ret = LTTCOMM_KERN_NA; + ret = LTTNG_ERR_KERN_NA; } goto error; } + /* Deny register consumer if we already have a spawned consumer. */ + if (cmd_ctx->lsm->cmd_type == LTTNG_REGISTER_CONSUMER) { + pthread_mutex_lock(&kconsumer_data.pid_mutex); + if (kconsumer_data.pid > 0) { + ret = LTTNG_ERR_KERN_CONSUMER_FAIL; + pthread_mutex_unlock(&kconsumer_data.pid_mutex); + goto error; + } + pthread_mutex_unlock(&kconsumer_data.pid_mutex); + } + /* * Check for command that don't needs to allocate a returned payload. We do * this here so we don't have to make the call for no payload at each @@ -4133,7 +2167,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, /* Commands that DO NOT need a session. */ switch (cmd_ctx->lsm->cmd_type) { case LTTNG_CREATE_SESSION: - case LTTNG_CREATE_SESSION_URI: case LTTNG_CALIBRATE: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: @@ -4151,10 +2184,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, cmd_ctx->session = session_find_by_name(cmd_ctx->lsm->session.name); if (cmd_ctx->session == NULL) { if (cmd_ctx->lsm->session.name != NULL) { - ret = LTTCOMM_SESS_NOT_FOUND; + ret = LTTNG_ERR_SESS_NOT_FOUND; } else { /* If no session name specified */ - ret = LTTCOMM_SELECT_SESS; + ret = LTTNG_ERR_SELECT_SESS; } goto error; } else { @@ -4167,13 +2200,14 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, if (!need_domain) { goto skip_domain; } + /* * Check domain type for specific "pre-action". */ switch (cmd_ctx->lsm->domain.type) { case LTTNG_DOMAIN_KERNEL: if (!is_root) { - ret = LTTCOMM_NEED_ROOT_SESSIOND; + ret = LTTNG_ERR_NEED_ROOT_SESSIOND; goto error; } @@ -4188,7 +2222,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, /* Consumer is in an ERROR state. Report back to client */ if (uatomic_read(&kernel_consumerd_state) == CONSUMER_ERROR) { - ret = LTTCOMM_NO_KERNCONSUMERD; + ret = LTTNG_ERR_NO_KERNCONSUMERD; goto error; } @@ -4197,7 +2231,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, if (cmd_ctx->session->kernel_session == NULL) { ret = create_kernel_session(cmd_ctx->session); if (ret < 0) { - ret = LTTCOMM_KERN_SESS_FAIL; + ret = LTTNG_ERR_KERN_SESS_FAIL; goto error; } } @@ -4205,21 +2239,28 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, /* Start the kernel consumer daemon */ pthread_mutex_lock(&kconsumer_data.pid_mutex); if (kconsumer_data.pid == 0 && - cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER && + cmd_ctx->session->start_consumer) { pthread_mutex_unlock(&kconsumer_data.pid_mutex); ret = start_consumerd(&kconsumer_data); if (ret < 0) { - ret = LTTCOMM_KERN_CONSUMER_FAIL; + ret = LTTNG_ERR_KERN_CONSUMER_FAIL; goto error; } uatomic_set(&kernel_consumerd_state, CONSUMER_STARTED); - - /* Set consumer fd of the session */ - cmd_ctx->session->kernel_session->consumer_fd = - kconsumer_data.cmd_sock; } else { pthread_mutex_unlock(&kconsumer_data.pid_mutex); } + + /* + * The consumer was just spawned so we need to add the socket to + * the consumer output of the session if exist. + */ + ret = consumer_create_socket(&kconsumer_data, + cmd_ctx->session->kernel_session->consumer); + if (ret < 0) { + goto error; + } } break; @@ -4227,15 +2268,16 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, { /* Consumer is in an ERROR state. Report back to client */ if (uatomic_read(&ust_consumerd_state) == CONSUMER_ERROR) { - ret = LTTCOMM_NO_USTCONSUMERD; + ret = LTTNG_ERR_NO_USTCONSUMERD; goto error; } if (need_tracing_session) { + /* Create UST session if none exist. */ if (cmd_ctx->session->ust_session == NULL) { ret = create_ust_session(cmd_ctx->session, &cmd_ctx->lsm->domain); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto error; } } @@ -4245,37 +2287,60 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, pthread_mutex_lock(&ustconsumer64_data.pid_mutex); if (consumerd64_bin[0] != '\0' && ustconsumer64_data.pid == 0 && - cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER && + cmd_ctx->session->start_consumer) { pthread_mutex_unlock(&ustconsumer64_data.pid_mutex); ret = start_consumerd(&ustconsumer64_data); if (ret < 0) { - ret = LTTCOMM_UST_CONSUMER64_FAIL; - ust_consumerd64_fd = -EINVAL; + ret = LTTNG_ERR_UST_CONSUMER64_FAIL; + uatomic_set(&ust_consumerd64_fd, -EINVAL); goto error; } - ust_consumerd64_fd = ustconsumer64_data.cmd_sock; + uatomic_set(&ust_consumerd64_fd, ustconsumer64_data.cmd_sock); uatomic_set(&ust_consumerd_state, CONSUMER_STARTED); } else { pthread_mutex_unlock(&ustconsumer64_data.pid_mutex); } + + /* + * Setup socket for consumer 64 bit. No need for atomic access + * since it was set above and can ONLY be set in this thread. + */ + ret = consumer_create_socket(&ustconsumer64_data, + cmd_ctx->session->ust_session->consumer); + if (ret < 0) { + goto error; + } + /* 32-bit */ if (consumerd32_bin[0] != '\0' && ustconsumer32_data.pid == 0 && - cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER && + cmd_ctx->session->start_consumer) { pthread_mutex_unlock(&ustconsumer32_data.pid_mutex); ret = start_consumerd(&ustconsumer32_data); if (ret < 0) { - ret = LTTCOMM_UST_CONSUMER32_FAIL; - ust_consumerd32_fd = -EINVAL; + ret = LTTNG_ERR_UST_CONSUMER32_FAIL; + uatomic_set(&ust_consumerd32_fd, -EINVAL); goto error; } - ust_consumerd32_fd = ustconsumer32_data.cmd_sock; + uatomic_set(&ust_consumerd32_fd, ustconsumer32_data.cmd_sock); uatomic_set(&ust_consumerd_state, CONSUMER_STARTED); } else { pthread_mutex_unlock(&ustconsumer32_data.pid_mutex); } + + /* + * Setup socket for consumer 64 bit. No need for atomic access + * since it was set above and can ONLY be set in this thread. + */ + ret = consumer_create_socket(&ustconsumer32_data, + cmd_ctx->session->ust_session->consumer); + if (ret < 0) { + goto error; + } } break; } @@ -4290,13 +2355,13 @@ skip_domain: switch (cmd_ctx->lsm->domain.type) { case LTTNG_DOMAIN_UST: if (uatomic_read(&ust_consumerd_state) != CONSUMER_STARTED) { - ret = LTTCOMM_NO_USTCONSUMERD; + ret = LTTNG_ERR_NO_USTCONSUMERD; goto error; } break; case LTTNG_DOMAIN_KERNEL: if (uatomic_read(&kernel_consumerd_state) != CONSUMER_STARTED) { - ret = LTTCOMM_NO_KERNCONSUMERD; + ret = LTTNG_ERR_NO_KERNCONSUMERD; goto error; } break; @@ -4311,7 +2376,7 @@ skip_domain: if (!session_access_ok(cmd_ctx->session, LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds))) { - ret = LTTCOMM_EPERM; + ret = LTTNG_ERR_EPERM; goto error; } } @@ -4355,19 +2420,38 @@ skip_domain: case LTTNG_ENABLE_CHANNEL: { ret = cmd_enable_channel(cmd_ctx->session, cmd_ctx->lsm->domain.type, - &cmd_ctx->lsm->u.channel.chan); + &cmd_ctx->lsm->u.channel.chan, kernel_poll_pipe[1]); break; } case LTTNG_ENABLE_CONSUMER: { + /* + * XXX: 0 means that this URI should be applied on the session. Should + * be a DOMAIN enuam. + */ ret = cmd_enable_consumer(cmd_ctx->lsm->domain.type, cmd_ctx->session); + if (ret != LTTNG_OK) { + goto error; + } + + if (cmd_ctx->lsm->domain.type == 0) { + /* Add the URI for the UST session if a consumer is present. */ + if (cmd_ctx->session->ust_session && + cmd_ctx->session->ust_session->consumer) { + ret = cmd_enable_consumer(LTTNG_DOMAIN_UST, cmd_ctx->session); + } else if (cmd_ctx->session->kernel_session && + cmd_ctx->session->kernel_session->consumer) { + ret = cmd_enable_consumer(LTTNG_DOMAIN_KERNEL, + cmd_ctx->session); + } + } break; } case LTTNG_ENABLE_EVENT: { ret = cmd_enable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type, cmd_ctx->lsm->u.enable.channel_name, - &cmd_ctx->lsm->u.enable.event); + &cmd_ctx->lsm->u.enable.event, kernel_poll_pipe[1]); break; } case LTTNG_ENABLE_ALL_EVENT: @@ -4376,7 +2460,7 @@ skip_domain: ret = cmd_enable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type, cmd_ctx->lsm->u.enable.channel_name, - cmd_ctx->lsm->u.enable.event.type); + cmd_ctx->lsm->u.enable.event.type, kernel_poll_pipe[1]); break; } case LTTNG_LIST_TRACEPOINTS: @@ -4386,6 +2470,7 @@ skip_domain: nb_events = cmd_list_tracepoints(cmd_ctx->lsm->domain.type, &events); if (nb_events < 0) { + /* Return value is a negative lttng_error_code. */ ret = -nb_events; goto error; } @@ -4406,7 +2491,7 @@ skip_domain: free(events); - ret = LTTCOMM_OK; + ret = LTTNG_OK; break; } case LTTNG_LIST_TRACEPOINT_FIELDS: @@ -4414,8 +2499,10 @@ skip_domain: struct lttng_event_field *fields; ssize_t nb_fields; - nb_fields = cmd_list_tracepoint_fields(cmd_ctx->lsm->domain.type, &fields); + nb_fields = cmd_list_tracepoint_fields(cmd_ctx->lsm->domain.type, + &fields); if (nb_fields < 0) { + /* Return value is a negative lttng_error_code. */ ret = -nb_fields; goto error; } @@ -4424,7 +2511,8 @@ skip_domain: * Setup lttng message with payload size set to the event list size in * bytes and then copy list into the llm payload. */ - ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_event_field) * nb_fields); + ret = setup_lttng_msg(cmd_ctx, + sizeof(struct lttng_event_field) * nb_fields); if (ret < 0) { free(fields); goto setup_error; @@ -4436,13 +2524,65 @@ skip_domain: free(fields); - ret = LTTCOMM_OK; + ret = LTTNG_OK; break; } case LTTNG_SET_CONSUMER_URI: { + size_t nb_uri, len; + struct lttng_uri *uris; + + nb_uri = cmd_ctx->lsm->u.uri.size; + len = nb_uri * sizeof(struct lttng_uri); + + if (nb_uri == 0) { + ret = LTTNG_ERR_INVALID; + goto error; + } + + uris = zmalloc(len); + if (uris == NULL) { + ret = LTTNG_ERR_FATAL; + goto error; + } + + /* Receive variable len data */ + DBG("Receiving %zu URI(s) from client ...", nb_uri); + ret = lttcomm_recv_unix_sock(sock, uris, len); + if (ret <= 0) { + DBG("No URIs received from client... continuing"); + *sock_error = 1; + ret = LTTNG_ERR_SESSION_FAIL; + free(uris); + goto error; + } + ret = cmd_set_consumer_uri(cmd_ctx->lsm->domain.type, cmd_ctx->session, - &cmd_ctx->lsm->u.uri); + nb_uri, uris); + if (ret != LTTNG_OK) { + free(uris); + goto error; + } + + /* + * XXX: 0 means that this URI should be applied on the session. Should + * be a DOMAIN enuam. + */ + if (cmd_ctx->lsm->domain.type == 0) { + /* Add the URI for the UST session if a consumer is present. */ + if (cmd_ctx->session->ust_session && + cmd_ctx->session->ust_session->consumer) { + ret = cmd_set_consumer_uri(LTTNG_DOMAIN_UST, cmd_ctx->session, + nb_uri, uris); + } else if (cmd_ctx->session->kernel_session && + cmd_ctx->session->kernel_session->consumer) { + ret = cmd_set_consumer_uri(LTTNG_DOMAIN_KERNEL, + cmd_ctx->session, nb_uri, uris); + } + } + + free(uris); + break; } case LTTNG_START_TRACE: @@ -4457,26 +2597,50 @@ skip_domain: } case LTTNG_CREATE_SESSION: { - ret = cmd_create_session(cmd_ctx->lsm->session.name, - cmd_ctx->lsm->session.path, &cmd_ctx->creds); - break; - } - case LTTNG_CREATE_SESSION_URI: - { - ret = cmd_create_session_uri(cmd_ctx->lsm->session.name, - &cmd_ctx->lsm->u.create_uri.ctrl_uri, - &cmd_ctx->lsm->u.create_uri.data_uri, - cmd_ctx->lsm->u.create_uri.enable_consumer, &cmd_ctx->creds); + size_t nb_uri, len; + struct lttng_uri *uris = NULL; + + nb_uri = cmd_ctx->lsm->u.uri.size; + len = nb_uri * sizeof(struct lttng_uri); + + if (nb_uri > 0) { + uris = zmalloc(len); + if (uris == NULL) { + ret = LTTNG_ERR_FATAL; + goto error; + } + + /* Receive variable len data */ + DBG("Waiting for %zu URIs from client ...", nb_uri); + ret = lttcomm_recv_unix_sock(sock, uris, len); + if (ret <= 0) { + DBG("No URIs received from client... continuing"); + *sock_error = 1; + ret = LTTNG_ERR_SESSION_FAIL; + free(uris); + goto error; + } + + if (nb_uri == 1 && uris[0].dtype != LTTNG_DST_PATH) { + DBG("Creating session with ONE network URI is a bad call"); + ret = LTTNG_ERR_SESSION_FAIL; + free(uris); + goto error; + } + } + + ret = cmd_create_session_uri(cmd_ctx->lsm->session.name, uris, nb_uri, + &cmd_ctx->creds); + + free(uris); + break; } case LTTNG_DESTROY_SESSION: { - ret = cmd_destroy_session(cmd_ctx->session, - cmd_ctx->lsm->session.name); - /* - * Set session to NULL so we do not unlock it after - * free. - */ + ret = cmd_destroy_session(cmd_ctx->session, kernel_poll_pipe[1]); + + /* Set session to NULL so we do not unlock it after free. */ cmd_ctx->session = NULL; break; } @@ -4487,6 +2651,7 @@ skip_domain: nb_dom = cmd_list_domains(cmd_ctx->session, &domains); if (nb_dom < 0) { + /* Return value is a negative lttng_error_code. */ ret = -nb_dom; goto error; } @@ -4502,7 +2667,7 @@ skip_domain: free(domains); - ret = LTTCOMM_OK; + ret = LTTNG_OK; break; } case LTTNG_LIST_CHANNELS: @@ -4513,6 +2678,7 @@ skip_domain: nb_chan = cmd_list_channels(cmd_ctx->lsm->domain.type, cmd_ctx->session, &channels); if (nb_chan < 0) { + /* Return value is a negative lttng_error_code. */ ret = -nb_chan; goto error; } @@ -4528,7 +2694,7 @@ skip_domain: free(channels); - ret = LTTCOMM_OK; + ret = LTTNG_OK; break; } case LTTNG_LIST_EVENTS: @@ -4539,6 +2705,7 @@ skip_domain: nb_event = cmd_list_events(cmd_ctx->lsm->domain.type, cmd_ctx->session, cmd_ctx->lsm->u.list.channel_name, &events); if (nb_event < 0) { + /* Return value is a negative lttng_error_code. */ ret = -nb_event; goto error; } @@ -4554,7 +2721,7 @@ skip_domain: free(events); - ret = LTTCOMM_OK; + ret = LTTNG_OK; break; } case LTTNG_LIST_SESSIONS: @@ -4573,13 +2740,13 @@ skip_domain: } /* Filled the session array */ - list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload), + cmd_list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload), LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds)); session_unlock_list(); - ret = LTTCOMM_OK; + ret = LTTNG_OK; break; } case LTTNG_CALIBRATE: @@ -4590,21 +2757,32 @@ skip_domain: } case LTTNG_REGISTER_CONSUMER: { + struct consumer_data *cdata; + + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + cdata = &kconsumer_data; + break; + default: + ret = LTTNG_ERR_UND; + goto error; + } + ret = cmd_register_consumer(cmd_ctx->session, cmd_ctx->lsm->domain.type, - cmd_ctx->lsm->u.reg.path); + cmd_ctx->lsm->u.reg.path, cdata); break; } case LTTNG_SET_FILTER: { struct lttng_filter_bytecode *bytecode; - if (cmd_ctx->lsm->u.filter.bytecode_len > 65336) { - ret = LTTCOMM_FILTER_INVAL; + if (cmd_ctx->lsm->u.filter.bytecode_len > LTTNG_FILTER_MAX_LEN) { + ret = LTTNG_ERR_FILTER_INVAL; goto error; } bytecode = zmalloc(cmd_ctx->lsm->u.filter.bytecode_len); if (!bytecode) { - ret = LTTCOMM_FILTER_NOMEM; + ret = LTTNG_ERR_FILTER_NOMEM; goto error; } /* Receive var. len. data */ @@ -4614,14 +2792,14 @@ skip_domain: if (ret <= 0) { DBG("Nothing recv() from client var len data... continuing"); *sock_error = 1; - ret = LTTCOMM_FILTER_INVAL; + ret = LTTNG_ERR_FILTER_INVAL; goto error; } if (bytecode->len + sizeof(*bytecode) != cmd_ctx->lsm->u.filter.bytecode_len) { free(bytecode); - ret = LTTCOMM_FILTER_INVAL; + ret = LTTNG_ERR_FILTER_INVAL; goto error; } @@ -4631,8 +2809,13 @@ skip_domain: bytecode); break; } + case LTTNG_DATA_AVAILABLE: + { + ret = cmd_data_available(cmd_ctx->session); + break; + } default: - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; break; } @@ -4661,7 +2844,7 @@ init_setup_error: */ static void *thread_manage_health(void *data) { - int sock = -1, new_sock, ret, i, pollfd, err = -1; + int sock = -1, new_sock = -1, ret, i, pollfd, err = -1; uint32_t revents, nb_fd; struct lttng_poll_event events; struct lttcomm_health_msg msg; @@ -4782,7 +2965,7 @@ restart: check_consumer_health(); break; default: - reply.ret_code = LTTCOMM_UND; + reply.ret_code = LTTNG_ERR_UND; break; } @@ -4851,6 +3034,8 @@ static void *thread_manage_clients(void *data) DBG("[thread] Manage client started"); + testpoint(thread_manage_clients); + rcu_register_thread(); health_code_update(&health_thread_cmd); @@ -4882,6 +3067,8 @@ static void *thread_manage_clients(void *data) kill(ppid, SIGUSR1); } + testpoint(thread_manage_clients_before_loop); + health_code_update(&health_thread_cmd); while (1) { @@ -5778,11 +3965,7 @@ int main(int argc, char **argv) /* Set up max poll set size */ lttng_poll_set_max_size(); - /* - * Set network sequence index to 1 for streams to match a relayd socket on - * the consumer side. - */ - uatomic_set(&relayd_net_seq_idx, 1); + cmd_init(); /* Init all health thread counters. */ health_init(&health_thread_cmd); @@ -5802,6 +3985,9 @@ int main(int argc, char **argv) health_init(&ustconsumer64_data.health); health_poll_update(&ustconsumer64_data.health); + /* Not needed anymore. */ + free(rundir); + /* Create thread to manage the client socket */ ret = pthread_create(&health_thread, NULL, thread_manage_health, (void *) NULL);