-
- 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, kernel_poll_pipe[1]);
- break;
- }
- case LTTNG_ENABLE_ALL_EVENT:
- {
- DBG("Enabling all events");
-
- ret = cmd_enable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.enable.channel_name,
- cmd_ctx->lsm->u.enable.event.type, kernel_poll_pipe[1]);
- break;
- }
- case LTTNG_LIST_TRACEPOINTS:
- {
- struct lttng_event *events;
- ssize_t nb_events;
-
- 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;
- }
-
- /*
- * 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) * nb_events);
- if (ret < 0) {
- free(events);
- goto setup_error;
- }
-
- /* Copy event list into message payload */
- memcpy(cmd_ctx->llm->payload, events,
- sizeof(struct lttng_event) * nb_events);
-
- free(events);
-
- ret = LTTNG_OK;
- break;
- }
- case LTTNG_LIST_TRACEPOINT_FIELDS:
- {
- struct lttng_event_field *fields;
- ssize_t nb_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;
- }
-
- /*
- * 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);
- if (ret < 0) {
- free(fields);
- goto setup_error;
- }
-
- /* Copy event list into message payload */
- memcpy(cmd_ctx->llm->payload, fields,
- sizeof(struct lttng_event_field) * nb_fields);
-
- free(fields);
-
- 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,
- 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:
- {
- ret = cmd_start_trace(cmd_ctx->session);
- break;
- }
- case LTTNG_STOP_TRACE:
- {
- ret = cmd_stop_trace(cmd_ctx->session);
- break;
- }
- case LTTNG_CREATE_SESSION:
- {
- 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, kernel_poll_pipe[1]);
-
- /* Set session to NULL so we do not unlock it after free. */
- cmd_ctx->session = NULL;
- break;
- }
- case LTTNG_LIST_DOMAINS:
- {
- ssize_t nb_dom;
- struct lttng_domain *domains;
-
- 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;
- }
-
- ret = setup_lttng_msg(cmd_ctx, nb_dom * sizeof(struct lttng_domain));
- if (ret < 0) {
- goto setup_error;
- }
-
- /* Copy event list into message payload */
- memcpy(cmd_ctx->llm->payload, domains,
- nb_dom * sizeof(struct lttng_domain));
-
- free(domains);
-
- ret = LTTNG_OK;
- break;
- }
- case LTTNG_LIST_CHANNELS:
- {
- int nb_chan;
- struct lttng_channel *channels;
-
- 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;
- }
-
- ret = setup_lttng_msg(cmd_ctx, nb_chan * sizeof(struct lttng_channel));
- if (ret < 0) {
- goto setup_error;
- }
-
- /* Copy event list into message payload */
- memcpy(cmd_ctx->llm->payload, channels,
- nb_chan * sizeof(struct lttng_channel));
-
- free(channels);
-
- ret = LTTNG_OK;
- break;
- }
- case LTTNG_LIST_EVENTS:
- {
- ssize_t nb_event;
- struct lttng_event *events = NULL;
-
- 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;
- }
-
- ret = setup_lttng_msg(cmd_ctx, nb_event * sizeof(struct lttng_event));
- if (ret < 0) {
- goto setup_error;
- }
-
- /* Copy event list into message payload */
- memcpy(cmd_ctx->llm->payload, events,
- nb_event * sizeof(struct lttng_event));
-
- free(events);
-
- ret = LTTNG_OK;
- break;
- }
- case LTTNG_LIST_SESSIONS:
- {
- unsigned int nr_sessions;
-
- session_lock_list();
- nr_sessions = lttng_sessions_count(
- LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds),
- LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds));
-
- ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) * nr_sessions);
- if (ret < 0) {
- session_unlock_list();
- goto setup_error;
- }
-
- /* Filled the session array */
- 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 = LTTNG_OK;
- break;
- }
- case LTTNG_CALIBRATE:
- {
- ret = cmd_calibrate(cmd_ctx->lsm->domain.type,
- &cmd_ctx->lsm->u.calibrate);
- break;
- }
- case LTTNG_REGISTER_CONSUMER:
- {
- struct consumer_data *cdata;
-
- 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, cdata);
- break;
- }
- case LTTNG_SET_FILTER:
- {
- struct lttng_filter_bytecode *bytecode;
-
- 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 = LTTNG_ERR_FILTER_NOMEM;
- goto error;
- }
- /* Receive var. len. data */
- DBG("Receiving var len data from client ...");
- ret = lttcomm_recv_unix_sock(sock, bytecode,
- cmd_ctx->lsm->u.filter.bytecode_len);
- if (ret <= 0) {
- DBG("Nothing recv() from client var len data... continuing");
- *sock_error = 1;
- ret = LTTNG_ERR_FILTER_INVAL;
- goto error;
- }
-
- if (bytecode->len + sizeof(*bytecode)
- != cmd_ctx->lsm->u.filter.bytecode_len) {
- free(bytecode);
- ret = LTTNG_ERR_FILTER_INVAL;
- goto error;
- }
-
- ret = cmd_set_filter(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.filter.channel_name,
- cmd_ctx->lsm->u.filter.event_name,
- bytecode);
- break;
- }
- case LTTNG_DATA_PENDING:
- {
- ret = cmd_data_pending(cmd_ctx->session);
- break;
- }
- default:
- ret = LTTNG_ERR_UND;
- break;
- }
-
-error:
- if (cmd_ctx->llm == NULL) {
- DBG("Missing llm structure. Allocating one.");
- if (setup_lttng_msg(cmd_ctx, 0) < 0) {
- goto setup_error;
- }
- }
- /* Set return code */
- cmd_ctx->llm->ret_code = ret;
-setup_error:
- if (cmd_ctx->session) {
- session_unlock(cmd_ctx->session);
- }
- if (need_tracing_session) {
- session_unlock_list();
- }
-init_setup_error:
- return ret;
-}
-
-/*
- * Thread managing health check socket.
- */
-static void *thread_manage_health(void *data)
-{
- 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;
- struct lttcomm_health_data reply;
-
- DBG("[thread] Manage health check started");
-
- rcu_register_thread();
-
- /* Create unix socket */
- sock = lttcomm_create_unix_sock(health_unix_sock_path);
- if (sock < 0) {
- ERR("Unable to create health check Unix socket");
- ret = -1;
- goto error;
- }
-
- /*
- * Set the CLOEXEC flag. Return code is useless because either way, the
- * show must go on.
- */
- (void) utils_set_fd_cloexec(sock);
-
- ret = lttcomm_listen_unix_sock(sock);
- if (ret < 0) {
- goto error;
- }
-
- /*
- * Pass 2 as size here for the thread quit pipe and client_sock. Nothing
- * more will be added to this poll set.
- */
- ret = create_thread_poll_set(&events, 2);
- if (ret < 0) {
- goto error;
- }
-
- /* Add the application registration socket */
- ret = lttng_poll_add(&events, sock, LPOLLIN | LPOLLPRI);
- if (ret < 0) {
- goto error;
- }
-
- while (1) {
- DBG("Health check ready");
-
- nb_fd = LTTNG_POLL_GETNB(&events);
-
- /* Inifinite blocking call, waiting for transmission */
-restart:
- ret = lttng_poll_wait(&events, -1);
- if (ret < 0) {
- /*
- * Restart interrupted system call.
- */
- if (errno == EINTR) {
- goto restart;
- }
- goto error;
- }
-
- for (i = 0; i < nb_fd; i++) {
- /* 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 = check_thread_quit_pipe(pollfd, revents);
- if (ret) {
- err = 0;
- goto exit;
- }
-
- /* Event on the registration socket */
- if (pollfd == sock) {
- if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
- ERR("Health socket poll error");
- goto error;
- }
- }
- }
-
- new_sock = lttcomm_accept_unix_sock(sock);
- if (new_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(new_sock);
-
- DBG("Receiving data from client for health...");
- ret = lttcomm_recv_unix_sock(new_sock, (void *)&msg, sizeof(msg));
- if (ret <= 0) {
- DBG("Nothing recv() from client... continuing");
- ret = close(new_sock);
- if (ret) {
- PERROR("close");
- }
- new_sock = -1;
- continue;
- }
-
- rcu_thread_online();
-
- switch (msg.component) {
- case LTTNG_HEALTH_CMD:
- reply.ret_code = health_check_state(&health_thread_cmd);
- break;
- case LTTNG_HEALTH_APP_MANAGE:
- reply.ret_code = health_check_state(&health_thread_app_manage);
- break;
- case LTTNG_HEALTH_APP_REG:
- reply.ret_code = health_check_state(&health_thread_app_reg);
- break;
- case LTTNG_HEALTH_KERNEL:
- reply.ret_code = health_check_state(&health_thread_kernel);
- break;
- case LTTNG_HEALTH_CONSUMER:
- reply.ret_code = check_consumer_health();
- break;
- case LTTNG_HEALTH_ALL:
- reply.ret_code =
- health_check_state(&health_thread_app_manage) &&
- health_check_state(&health_thread_app_reg) &&
- health_check_state(&health_thread_cmd) &&
- health_check_state(&health_thread_kernel) &&
- check_consumer_health();
- break;
- default:
- reply.ret_code = LTTNG_ERR_UND;
- break;
- }
-
- /*
- * Flip ret value since 0 is a success and 1 indicates a bad health for
- * the client where in the sessiond it is the opposite. Again, this is
- * just to make things easier for us poor developer which enjoy a lot
- * lazyness.
- */
- if (reply.ret_code == 0 || reply.ret_code == 1) {
- reply.ret_code = !reply.ret_code;
- }
-
- DBG2("Health check return value %d", reply.ret_code);
-
- ret = send_unix_sock(new_sock, (void *) &reply, sizeof(reply));
- if (ret < 0) {
- ERR("Failed to send health data back to client");
- }
-
- /* End of transmission */
- ret = close(new_sock);
- if (ret) {
- PERROR("close");
- }
- new_sock = -1;
- }
-
-exit:
-error:
- if (err) {
- ERR("Health error occurred in %s", __func__);
- }
- DBG("Health check thread dying");
- unlink(health_unix_sock_path);
- if (sock >= 0) {
- ret = close(sock);
- if (ret) {
- PERROR("close");
- }
- }
- if (new_sock >= 0) {
- ret = close(new_sock);
- if (ret) {
- PERROR("close");
- }
- }
-
- lttng_poll_clean(&events);
-
- rcu_unregister_thread();
- return NULL;
-}
-
-/*
- * This thread manage all clients request using the unix client socket for
- * communication.
- */
-static void *thread_manage_clients(void *data)
-{
- int sock = -1, ret, i, pollfd, err = -1;
- int sock_error;
- uint32_t revents, nb_fd;
- struct command_ctx *cmd_ctx = NULL;
- struct lttng_poll_event events;
-
- DBG("[thread] Manage client started");
-
- testpoint(thread_manage_clients);
-
- rcu_register_thread();
-
- health_code_update(&health_thread_cmd);
-
- ret = lttcomm_listen_unix_sock(client_sock);
- if (ret < 0) {
- goto error;
- }
-
- /*
- * Pass 2 as size here for the thread quit pipe and client_sock. Nothing
- * more will be added to this poll set.
- */
- ret = create_thread_poll_set(&events, 2);
- if (ret < 0) {
- goto error;
- }
-
- /* Add the application registration socket */
- ret = lttng_poll_add(&events, client_sock, LPOLLIN | LPOLLPRI);
- if (ret < 0) {
- goto error;
- }
-
- /*
- * Notify parent pid that we are ready to accept command for client side.
- */
- if (opt_sig_parent) {
- kill(ppid, SIGUSR1);
- }
-
- testpoint(thread_manage_clients_before_loop);
-
- health_code_update(&health_thread_cmd);
-
- while (1) {
- DBG("Accepting client command ...");
-
- nb_fd = LTTNG_POLL_GETNB(&events);
-
- /* Inifinite blocking call, waiting for transmission */
- restart:
- health_poll_update(&health_thread_cmd);
- ret = lttng_poll_wait(&events, -1);
- health_poll_update(&health_thread_cmd);
- if (ret < 0) {
- /*
- * Restart interrupted system call.
- */
- if (errno == EINTR) {
- goto restart;