-
- if (app) {
- ret = send_app_sockets_to_threads(app);
- if (ret < 0) {
- goto error;
- }
- /*
- * @session_lock_list
- *
- * Lock the global session list so from the register up to the
- * registration done message, no thread can see the application
- * and change its state.
- */
- session_lock_list();
- rcu_read_lock();
- /*
- * Add application to the global hash table. This needs to be
- * done before the update to the UST registry can locate the
- * application.
- */
- ust_app_add(app);
- /*
- * Get app version.
- */
- ret = ust_app_version(app);
- if (ret) {
- ERR("Unable to get app version");
- }
- /*
- * Update newly registered application with the tracing
- * registry info already enabled information.
- */
- update_ust_app(app->sock);
- ret = ust_app_register_done(app->sock);
- if (ret < 0) {
- /* Remove application from the registry. */
- ust_app_unregister(app->sock);
- }
- rcu_read_unlock();
- session_unlock_list();
- } else {
- /* Application manager threads are not available. */
- ret = close(ust_cmd->sock);
- if (ret < 0) {
- PERROR("close ust_cmd sock");
- }
- }
- free(ust_cmd);
- } while (node != NULL);
-
- /* Futex wait on queue. Blocking call on futex() */
- futex_nto1_wait(&ust_cmd_queue.futex);
- }
-
-error:
- DBG("Dispatch thread dying");
- return NULL;
-}
-
-/*
- * This thread manage application registration.
- */
-static void *thread_registration_apps(void *data)
-{
- int sock = -1, i, ret, pollfd, err = -1;
- uint32_t revents, nb_fd;
- struct lttng_poll_event events;
- /*
- * Get allocated in this thread, enqueued to a global queue, dequeued and
- * freed in the manage apps thread.
- */
- struct ust_command *ust_cmd = NULL;
-
- DBG("[thread] Manage application registration started");
-
- health_register(HEALTH_TYPE_APP_REG);
-
- if (testpoint(thread_registration_apps)) {
- goto error_testpoint;
- }
-
- ret = lttcomm_listen_unix_sock(apps_sock);
- if (ret < 0) {
- goto error_listen;
- }
-
- /*
- * Pass 2 as size here for the thread quit pipe and apps socket. Nothing
- * more will be added to this poll set.
- */
- ret = sessiond_set_thread_pollset(&events, 2);
- if (ret < 0) {
- goto error_create_poll;
- }
-
- /* Add the application registration socket */
- ret = lttng_poll_add(&events, apps_sock, LPOLLIN | LPOLLRDHUP);
- if (ret < 0) {
- goto error_poll_add;
- }
-
- /* Notify all applications to register */
- ret = notify_ust_apps(1);
- if (ret < 0) {
- ERR("Failed to notify applications or create the wait shared memory.\n"
- "Execution continues but there might be problem for already\n"
- "running applications that wishes to register.");
- }
-
- while (1) {
- DBG("Accepting application registration");
-
- /* Inifinite blocking call, waiting for transmission */
- restart:
- health_poll_entry();
- ret = lttng_poll_wait(&events, -1);
- health_poll_exit();
- if (ret < 0) {
- /*
- * Restart interrupted system call.
- */
- if (errno == EINTR) {
- goto restart;
- }
- goto error;
- }
-
- nb_fd = ret;
-
- for (i = 0; i < nb_fd; i++) {
- health_code_update();
-
- /* Fetch once the poll data */
- revents = LTTNG_POLL_GETEV(&events, i);
- pollfd = LTTNG_POLL_GETFD(&events, i);
-
- /* Thread quit pipe has been closed. Killing thread. */
- ret = sessiond_check_thread_quit_pipe(pollfd, revents);
- if (ret) {
- err = 0;
- goto exit;
- }
-
- /* Event on the registration socket */
- if (pollfd == apps_sock) {
- if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
- ERR("Register apps socket poll error");
- goto error;
- } else if (revents & LPOLLIN) {
- sock = lttcomm_accept_unix_sock(apps_sock);
- if (sock < 0) {
- goto error;
- }
-
- /*
- * Set the CLOEXEC flag. Return code is useless because
- * either way, the show must go on.
- */
- (void) utils_set_fd_cloexec(sock);
-
- /* Create UST registration command for enqueuing */
- ust_cmd = zmalloc(sizeof(struct ust_command));
- if (ust_cmd == NULL) {
- PERROR("ust command zmalloc");
- goto error;
- }
-
- /*
- * Using message-based transmissions to ensure we don't
- * have to deal with partially received messages.
- */
- ret = lttng_fd_get(LTTNG_FD_APPS, 1);
- if (ret < 0) {
- ERR("Exhausted file descriptors allowed for applications.");
- free(ust_cmd);
- ret = close(sock);
- if (ret) {
- PERROR("close");
- }
- sock = -1;
- continue;
- }
- health_code_update();
- ret = ust_app_recv_registration(sock, &ust_cmd->reg_msg);
- if (ret < 0) {
- free(ust_cmd);
- /* Close socket of the application. */
- ret = close(sock);
- if (ret) {
- PERROR("close");
- }
- lttng_fd_put(LTTNG_FD_APPS, 1);
- sock = -1;
- continue;
- }
- health_code_update();
-
- ust_cmd->sock = sock;
- sock = -1;
-
- DBG("UST registration received with pid:%d ppid:%d uid:%d"
- " gid:%d sock:%d name:%s (version %d.%d)",
- ust_cmd->reg_msg.pid, ust_cmd->reg_msg.ppid,
- ust_cmd->reg_msg.uid, ust_cmd->reg_msg.gid,
- ust_cmd->sock, ust_cmd->reg_msg.name,
- ust_cmd->reg_msg.major, ust_cmd->reg_msg.minor);
-
- /*
- * Lock free enqueue the registration request. The red pill
- * has been taken! This apps will be part of the *system*.
- */
- cds_wfq_enqueue(&ust_cmd_queue.queue, &ust_cmd->node);
-
- /*
- * Wake the registration queue futex. Implicit memory
- * barrier with the exchange in cds_wfq_enqueue.
- */
- futex_nto1_wake(&ust_cmd_queue.futex);
- }
- }
- }
- }
-
-exit:
-error:
- if (err) {
- health_error();
- ERR("Health error occurred in %s", __func__);
- }
-
- /* Notify that the registration thread is gone */
- notify_ust_apps(0);
-
- if (apps_sock >= 0) {
- ret = close(apps_sock);
- if (ret) {
- PERROR("close");
- }
- }
- if (sock >= 0) {
- ret = close(sock);
- if (ret) {
- PERROR("close");
- }
- lttng_fd_put(LTTNG_FD_APPS, 1);
- }
- unlink(apps_unix_sock_path);
-
-error_poll_add:
- lttng_poll_clean(&events);
-error_listen:
-error_create_poll:
-error_testpoint:
- DBG("UST Registration thread cleanup complete");
- health_unregister();
-
- return NULL;
-}
-
-/*
- * Start the thread_manage_consumer. This must be done after a lttng-consumerd
- * exec or it will fails.
- */
-static int spawn_consumer_thread(struct consumer_data *consumer_data)
-{
- int ret, clock_ret;
- struct timespec timeout;
-
- /* Make sure we set the readiness flag to 0 because we are NOT ready */
- consumer_data->consumer_thread_is_ready = 0;
-
- /* 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);
- 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 */
- 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);
- }
- }
-
- /* 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("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("pthread_cond_wait failed consumer thread");
- }
- goto error;
- }
-
- pthread_mutex_lock(&consumer_data->pid_mutex);
- if (consumer_data->pid == 0) {
- ERR("Consumerd did not start");
- pthread_mutex_unlock(&consumer_data->pid_mutex);
- goto error;
- }
- pthread_mutex_unlock(&consumer_data->pid_mutex);
-
- return 0;
-
-error:
- return ret;
-}
-
-/*
- * Join consumer thread
- */
-static int join_consumer_thread(struct consumer_data *consumer_data)
-{
- void *status;
-
- /* Consumer pid must be a real one. */
- if (consumer_data->pid > 0) {
- int ret;
- ret = kill(consumer_data->pid, SIGTERM);
- if (ret) {
- ERR("Error killing consumer daemon");
- return ret;
- }
- return pthread_join(consumer_data->thread, &status);
- } else {
- return 0;
- }
-}
-
-/*
- * Fork and exec a consumer daemon (consumerd).
- *
- * Return pid if successful else -1.
- */
-static pid_t spawn_consumerd(struct consumer_data *consumer_data)
-{
- int ret;
- pid_t pid;
- const char *consumer_to_use;
- const char *verbosity;
- struct stat st;
-
- DBG("Spawning consumerd");
-
- pid = fork();
- if (pid == 0) {
- /*
- * Exec consumerd.
- */
- if (opt_verbose_consumer) {
- verbosity = "--verbose";
- } else {
- verbosity = "--quiet";
- }
- switch (consumer_data->type) {
- case LTTNG_CONSUMER_KERNEL:
- /*
- * Find out which consumerd to execute. We will first try the
- * 64-bit path, then the sessiond's installation directory, and
- * fallback on the 32-bit one,
- */
- DBG3("Looking for a kernel consumer at these locations:");
- DBG3(" 1) %s", consumerd64_bin);
- DBG3(" 2) %s/%s", INSTALL_BIN_PATH, CONSUMERD_FILE);
- DBG3(" 3) %s", consumerd32_bin);
- if (stat(consumerd64_bin, &st) == 0) {
- DBG3("Found location #1");
- consumer_to_use = consumerd64_bin;
- } else if (stat(INSTALL_BIN_PATH "/" CONSUMERD_FILE, &st) == 0) {
- DBG3("Found location #2");
- consumer_to_use = INSTALL_BIN_PATH "/" CONSUMERD_FILE;
- } else if (stat(consumerd32_bin, &st) == 0) {
- DBG3("Found location #3");
- consumer_to_use = consumerd32_bin;
- } else {
- DBG("Could not find any valid consumerd executable");
- break;
- }
- DBG("Using kernel consumer at: %s", consumer_to_use);
- execl(consumer_to_use,
- "lttng-consumerd", verbosity, "-k",
- "--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
- "--consumerd-err-sock", consumer_data->err_unix_sock_path,
- NULL);
- break;
- case LTTNG_CONSUMER64_UST:
- {
- char *tmpnew = NULL;
-
- if (consumerd64_libdir[0] != '\0') {
- char *tmp;
- size_t tmplen;
-
- tmp = getenv("LD_LIBRARY_PATH");
- if (!tmp) {
- tmp = "";
- }
- tmplen = strlen("LD_LIBRARY_PATH=")
- + strlen(consumerd64_libdir) + 1 /* : */ + strlen(tmp);
- tmpnew = zmalloc(tmplen + 1 /* \0 */);
- if (!tmpnew) {
- ret = -ENOMEM;
- goto error;
- }
- strcpy(tmpnew, "LD_LIBRARY_PATH=");
- strcat(tmpnew, consumerd64_libdir);
- if (tmp[0] != '\0') {
- strcat(tmpnew, ":");
- strcat(tmpnew, tmp);
- }
- ret = putenv(tmpnew);
- if (ret) {
- ret = -errno;
- goto error;
- }
- }
- DBG("Using 64-bit UST consumer at: %s", consumerd64_bin);
- ret = execl(consumerd64_bin, "lttng-consumerd", verbosity, "-u",
- "--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
- "--consumerd-err-sock", consumer_data->err_unix_sock_path,
- NULL);
- if (consumerd64_libdir[0] != '\0') {
- free(tmpnew);
- }
- if (ret) {
- goto error;
- }
- break;
- }
- case LTTNG_CONSUMER32_UST:
- {
- char *tmpnew = NULL;
-
- if (consumerd32_libdir[0] != '\0') {
- char *tmp;
- size_t tmplen;
-
- tmp = getenv("LD_LIBRARY_PATH");
- if (!tmp) {
- tmp = "";
- }
- tmplen = strlen("LD_LIBRARY_PATH=")
- + strlen(consumerd32_libdir) + 1 /* : */ + strlen(tmp);
- tmpnew = zmalloc(tmplen + 1 /* \0 */);
- if (!tmpnew) {
- ret = -ENOMEM;
- goto error;
- }
- strcpy(tmpnew, "LD_LIBRARY_PATH=");
- strcat(tmpnew, consumerd32_libdir);
- if (tmp[0] != '\0') {
- strcat(tmpnew, ":");
- strcat(tmpnew, tmp);
- }
- ret = putenv(tmpnew);
- if (ret) {
- ret = -errno;
- goto error;
- }
- }
- DBG("Using 32-bit UST consumer at: %s", consumerd32_bin);
- ret = execl(consumerd32_bin, "lttng-consumerd", verbosity, "-u",
- "--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
- "--consumerd-err-sock", consumer_data->err_unix_sock_path,
- NULL);
- if (consumerd32_libdir[0] != '\0') {
- free(tmpnew);
- }
- if (ret) {
- goto error;
- }
- 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;
- } else {
- PERROR("start consumer fork");
- ret = -errno;
- }
-error:
- return ret;
-}
-
-/*
- * Spawn the consumerd daemon and session daemon thread.
- */
-static int start_consumerd(struct consumer_data *consumer_data)
-{
- int ret;
-
- /*
- * Set the listen() state on the socket since there is a possible race
- * between the exec() of the consumer daemon and this call if place in the
- * consumer thread. See bug #366 for more details.
- */
- ret = lttcomm_listen_unix_sock(consumer_data->err_sock);
- if (ret < 0) {
- goto error;
- }
-
- pthread_mutex_lock(&consumer_data->pid_mutex);
- if (consumer_data->pid != 0) {
- pthread_mutex_unlock(&consumer_data->pid_mutex);
- goto end;
- }
-
- ret = spawn_consumerd(consumer_data);
- if (ret < 0) {
- ERR("Spawning consumerd failed");
- pthread_mutex_unlock(&consumer_data->pid_mutex);
- goto error;
- }
-
- /* Setting up the consumer_data pid */
- consumer_data->pid = ret;
- DBG2("Consumer pid %d", consumer_data->pid);
- pthread_mutex_unlock(&consumer_data->pid_mutex);
-
- DBG2("Spawning consumer control thread");
- ret = spawn_consumer_thread(consumer_data);
- if (ret < 0) {
- ERR("Fatal error spawning consumer control thread");
- goto error;
- }
-
-end:
- return 0;
-
-error:
- /* Cleanup already created socket on error. */
- if (consumer_data->err_sock >= 0) {
- int err;
-
- err = close(consumer_data->err_sock);
- if (err < 0) {
- PERROR("close consumer data error socket");
- }
- }
- return ret;
-}
-
-/*
- * Compute health status of each consumer. If one of them is zero (bad
- * state), we return 0.
- */
-static int check_consumer_health(void)
-{
- int ret;
-
- ret = health_check_state(HEALTH_TYPE_CONSUMER);
-
- DBG3("Health consumer check %d", ret);
-
- return ret;
-}
-
-/*
- * Setup necessary data for kernel tracer action.
- */
-static int init_kernel_tracer(void)
-{
- int ret;
-
- /* Modprobe lttng kernel modules */
- ret = modprobe_lttng_control();
- if (ret < 0) {
- goto error;
- }
-
- /* Open debugfs lttng */
- kernel_tracer_fd = open(module_proc_lttng, O_RDWR);
- if (kernel_tracer_fd < 0) {
- DBG("Failed to open %s", module_proc_lttng);
- ret = -1;
- goto error_open;
- }
-
- /* Validate kernel version */
- ret = kernel_validate_version(kernel_tracer_fd);
- if (ret < 0) {
- goto error_version;
- }
-
- ret = modprobe_lttng_data();
- if (ret < 0) {
- goto error_modules;
- }
-
- DBG("Kernel tracer fd %d", kernel_tracer_fd);
- return 0;
-
-error_version:
- modprobe_remove_lttng_control();
- ret = close(kernel_tracer_fd);
- if (ret) {
- PERROR("close");
- }
- kernel_tracer_fd = -1;
- return LTTNG_ERR_KERN_VERSION;
-
-error_modules:
- ret = close(kernel_tracer_fd);
- if (ret) {
- PERROR("close");
- }
-
-error_open:
- modprobe_remove_lttng_control();
-
-error:
- WARN("No kernel tracer available");
- kernel_tracer_fd = -1;
- if (!is_root) {
- return LTTNG_ERR_NEED_ROOT_SESSIOND;
- } else {
- return LTTNG_ERR_KERN_NA;
- }
-}
-
-
-/*
- * Copy consumer output from the tracing session to the domain session. The
- * function also applies the right modification on a per domain basis for the
- * trace files destination directory.
- */
-static int copy_session_consumer(int domain, struct ltt_session *session)
-{
- int ret;
- 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 */
- consumer = session->kernel_session->consumer;
- dir_name = DEFAULT_KERNEL_TRACE_DIR;
- 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 */
- consumer = session->ust_session->consumer;
- dir_name = DEFAULT_UST_TRACE_DIR;
- break;
- default:
- ret = LTTNG_ERR_UNKNOWN_DOMAIN;
- goto error;
- }
-
- /* Append correct directory to subdir */
- strncat(consumer->subdir, dir_name,
- sizeof(consumer->subdir) - strlen(consumer->subdir) - 1);
- DBG3("Copy session consumer subdir %s", consumer->subdir);
-
- ret = LTTNG_OK;
-
-error:
- return ret;
-}
-
-/*
- * Create an UST session and add it to the session ust list.
- */
-static int create_ust_session(struct ltt_session *session,
- struct lttng_domain *domain)
-{
- int ret;
- struct ltt_ust_session *lus = NULL;
-
- assert(session);
- assert(domain);
- assert(session->consumer);
-
- switch (domain->type) {
- case LTTNG_DOMAIN_UST:
- break;
- default:
- ERR("Unknown UST domain on create session %d", domain->type);
- ret = LTTNG_ERR_UNKNOWN_DOMAIN;
- goto error;
- }
-
- DBG("Creating UST session");
-
- lus = trace_ust_create_session(session->path, session->id);
- if (lus == NULL) {
- ret = LTTNG_ERR_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 != LTTNG_OK) {
- goto error;
- }
-
- return LTTNG_OK;
-
-error:
- free(lus);
- session->ust_session = NULL;
- return ret;
-}
-
-/*
- * Create a kernel tracer session then create the default channel.
- */
-static int create_kernel_session(struct ltt_session *session)
-{
- int ret;
-
- DBG("Creating kernel session");
-
- ret = kernel_create_session(session, kernel_tracer_fd);
- if (ret < 0) {
- ret = LTTNG_ERR_KERN_SESS_FAIL;
- goto error;
- }
-
- /* 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 != LTTNG_OK) {
- goto error;
- }
-
- /* Create directory(ies) on local filesystem. */
- 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);
- if (ret < 0) {
- if (ret != -EEXIST) {
- ERR("Trace directory creation error");
- goto error;
- }
- }
- }
-
- session->kernel_session->uid = session->uid;
- session->kernel_session->gid = session->gid;
-
- return LTTNG_OK;
-
-error:
- trace_kernel_destroy_session(session->kernel_session);
- session->kernel_session = NULL;
- return ret;
-}
-
-/*
- * Count number of session permitted by uid/gid.
- */
-static unsigned int lttng_sessions_count(uid_t uid, gid_t gid)
-{
- unsigned int i = 0;
- struct ltt_session *session;
-
- DBG("Counting number of available session for UID %d GID %d",
- uid, gid);
- 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;
- }
- i++;
- }
- return i;
-}
-
-/*
- * 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 = LTTNG_OK;
- int need_tracing_session = 1;
- int need_domain;
-
- DBG("Processing client command %d", cmd_ctx->lsm->cmd_type);
-
- *sock_error = 0;
-
- switch (cmd_ctx->lsm->cmd_type) {
- case LTTNG_CREATE_SESSION:
- case LTTNG_DESTROY_SESSION:
- case LTTNG_LIST_SESSIONS:
- case LTTNG_LIST_DOMAINS:
- case LTTNG_START_TRACE:
- case LTTNG_STOP_TRACE:
- case LTTNG_DATA_PENDING:
- need_domain = 0;
- break;
- default:
- need_domain = 1;
- }
-
- if (opt_no_kernel && need_domain
- && cmd_ctx->lsm->domain.type == LTTNG_DOMAIN_KERNEL) {
- if (!is_root) {
- ret = LTTNG_ERR_NEED_ROOT_SESSIOND;
- } else {
- 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
- * command.
- */
- switch(cmd_ctx->lsm->cmd_type) {
- case LTTNG_LIST_SESSIONS:
- case LTTNG_LIST_TRACEPOINTS:
- case LTTNG_LIST_TRACEPOINT_FIELDS:
- case LTTNG_LIST_DOMAINS:
- case LTTNG_LIST_CHANNELS:
- case LTTNG_LIST_EVENTS:
- break;
- default:
- /* Setup lttng message with no payload */
- ret = setup_lttng_msg(cmd_ctx, 0);
- if (ret < 0) {
- /* This label does not try to unlock the session */
- goto init_setup_error;
- }
- }
-
- /* Commands that DO NOT need a session. */
- switch (cmd_ctx->lsm->cmd_type) {
- case LTTNG_CREATE_SESSION:
- case LTTNG_CALIBRATE:
- case LTTNG_LIST_SESSIONS:
- case LTTNG_LIST_TRACEPOINTS:
- case LTTNG_LIST_TRACEPOINT_FIELDS:
- need_tracing_session = 0;
- break;
- default:
- DBG("Getting session %s by name", cmd_ctx->lsm->session.name);
- /*
- * We keep the session list lock across _all_ commands
- * for now, because the per-session lock does not
- * handle teardown properly.
- */
- session_lock_list();
- 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 = LTTNG_ERR_SESS_NOT_FOUND;
- } else {
- /* If no session name specified */
- ret = LTTNG_ERR_SELECT_SESS;
- }
- goto error;
- } else {
- /* Acquire lock for the session */
- session_lock(cmd_ctx->session);
- }
- break;
- }
-
- 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 = LTTNG_ERR_NEED_ROOT_SESSIOND;
- goto error;