-
- /* Consumer is in an ERROR state. Report back to client */
- if (uatomic_read(&kernel_consumerd_state) == CONSUMER_ERROR) {
- ret = LTTNG_ERR_NO_KERNCONSUMERD;
- goto error;
- }
-
- /* Need a session for kernel command */
- if (need_tracing_session) {
- if (cmd_ctx->session->kernel_session == NULL) {
- ret = create_kernel_session(cmd_ctx->session);
- if (ret < 0) {
- ret = LTTNG_ERR_KERN_SESS_FAIL;
- goto error;
- }
- }
-
- /* 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) {
- pthread_mutex_unlock(&kconsumer_data.pid_mutex);
- ret = start_consumerd(&kconsumer_data);
- if (ret < 0) {
- ret = LTTNG_ERR_KERN_CONSUMER_FAIL;
- goto error;
- }
- uatomic_set(&kernel_consumerd_state, CONSUMER_STARTED);
- } 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;
- case LTTNG_DOMAIN_JUL:
- case LTTNG_DOMAIN_LOG4J:
- case LTTNG_DOMAIN_UST:
- {
- if (!ust_app_supported()) {
- ret = LTTNG_ERR_NO_UST;
- goto error;
- }
- /* Consumer is in an ERROR state. Report back to client */
- if (uatomic_read(&ust_consumerd_state) == CONSUMER_ERROR) {
- 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 != LTTNG_OK) {
- goto error;
- }
- }
-
- /* Start the UST consumer daemons */
- /* 64-bit */
- pthread_mutex_lock(&ustconsumer64_data.pid_mutex);
- if (consumerd64_bin[0] != '\0' &&
- ustconsumer64_data.pid == 0 &&
- cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
- pthread_mutex_unlock(&ustconsumer64_data.pid_mutex);
- ret = start_consumerd(&ustconsumer64_data);
- if (ret < 0) {
- ret = LTTNG_ERR_UST_CONSUMER64_FAIL;
- uatomic_set(&ust_consumerd64_fd, -EINVAL);
- goto error;
- }
-
- 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 */
- pthread_mutex_lock(&ustconsumer32_data.pid_mutex);
- if (consumerd32_bin[0] != '\0' &&
- ustconsumer32_data.pid == 0 &&
- cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
- pthread_mutex_unlock(&ustconsumer32_data.pid_mutex);
- ret = start_consumerd(&ustconsumer32_data);
- if (ret < 0) {
- ret = LTTNG_ERR_UST_CONSUMER32_FAIL;
- uatomic_set(&ust_consumerd32_fd, -EINVAL);
- goto error;
- }
-
- 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;
- }
- default:
- break;
- }
-skip_domain:
-
- /* Validate consumer daemon state when start/stop trace command */
- if (cmd_ctx->lsm->cmd_type == LTTNG_START_TRACE ||
- cmd_ctx->lsm->cmd_type == LTTNG_STOP_TRACE) {
- switch (cmd_ctx->lsm->domain.type) {
- case LTTNG_DOMAIN_JUL:
- case LTTNG_DOMAIN_LOG4J:
- case LTTNG_DOMAIN_UST:
- if (uatomic_read(&ust_consumerd_state) != CONSUMER_STARTED) {
- ret = LTTNG_ERR_NO_USTCONSUMERD;
- goto error;
- }
- break;
- case LTTNG_DOMAIN_KERNEL:
- if (uatomic_read(&kernel_consumerd_state) != CONSUMER_STARTED) {
- ret = LTTNG_ERR_NO_KERNCONSUMERD;
- goto error;
- }
- break;
- }
- }
-
- /*
- * Check that the UID or GID match that of the tracing session.
- * The root user can interact with all sessions.
- */
- if (need_tracing_session) {
- if (!session_access_ok(cmd_ctx->session,
- LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds),
- LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds))) {
- ret = LTTNG_ERR_EPERM;
- goto error;
- }
- }
-
- /*
- * Send relayd information to consumer as soon as we have a domain and a
- * session defined.
- */
- if (cmd_ctx->session && need_domain) {
- /*
- * Setup relayd if not done yet. If the relayd information was already
- * sent to the consumer, this call will gracefully return.
- */
- ret = cmd_setup_relayd(cmd_ctx->session);
- if (ret != LTTNG_OK) {
- goto error;
- }
- }
-
- /* Process by command type */
- switch (cmd_ctx->lsm->cmd_type) {
- case LTTNG_ADD_CONTEXT:
- {
- ret = cmd_add_context(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.context.channel_name,
- &cmd_ctx->lsm->u.context.ctx, kernel_poll_pipe[1]);
- break;
- }
- case LTTNG_DISABLE_CHANNEL:
- {
- ret = cmd_disable_channel(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.disable.channel_name);
- break;
- }
- case LTTNG_DISABLE_EVENT:
- {
- /* FIXME: passing packed structure to non-packed pointer */
- /* TODO: handle filter */
- ret = cmd_disable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.disable.channel_name,
- &cmd_ctx->lsm->u.disable.event);
- break;
- }
- case LTTNG_ENABLE_CHANNEL:
- {
- ret = cmd_enable_channel(cmd_ctx->session, &cmd_ctx->lsm->domain,
- &cmd_ctx->lsm->u.channel.chan, kernel_poll_pipe[1]);
- break;
- }
- case LTTNG_ENABLE_EVENT:
- {
- struct lttng_event_exclusion *exclusion = NULL;
- struct lttng_filter_bytecode *bytecode = NULL;
- char *filter_expression = NULL;
-
- /* Handle exclusion events and receive it from the client. */
- if (cmd_ctx->lsm->u.enable.exclusion_count > 0) {
- size_t count = cmd_ctx->lsm->u.enable.exclusion_count;
-
- exclusion = zmalloc(sizeof(struct lttng_event_exclusion) +
- (count * LTTNG_SYMBOL_NAME_LEN));
- if (!exclusion) {
- ret = LTTNG_ERR_EXCLUSION_NOMEM;
- goto error;
- }
-
- DBG("Receiving var len exclusion event list from client ...");
- exclusion->count = count;
- ret = lttcomm_recv_unix_sock(sock, exclusion->names,
- count * LTTNG_SYMBOL_NAME_LEN);
- if (ret <= 0) {
- DBG("Nothing recv() from client var len data... continuing");
- *sock_error = 1;
- free(exclusion);
- ret = LTTNG_ERR_EXCLUSION_INVAL;
- goto error;
- }
- }
-
- /* Get filter expression from client. */
- if (cmd_ctx->lsm->u.enable.expression_len > 0) {
- size_t expression_len =
- cmd_ctx->lsm->u.enable.expression_len;
-
- if (expression_len > LTTNG_FILTER_MAX_LEN) {
- ret = LTTNG_ERR_FILTER_INVAL;
- free(exclusion);
- goto error;
- }
-
- filter_expression = zmalloc(expression_len);
- if (!filter_expression) {
- free(exclusion);
- ret = LTTNG_ERR_FILTER_NOMEM;
- goto error;
- }
-
- /* Receive var. len. data */
- DBG("Receiving var len filter's expression from client ...");
- ret = lttcomm_recv_unix_sock(sock, filter_expression,
- expression_len);
- if (ret <= 0) {
- DBG("Nothing recv() from client car len data... continuing");
- *sock_error = 1;
- free(filter_expression);
- free(exclusion);
- ret = LTTNG_ERR_FILTER_INVAL;
- goto error;
- }
- }
-
- /* Handle filter and get bytecode from client. */
- if (cmd_ctx->lsm->u.enable.bytecode_len > 0) {
- size_t bytecode_len = cmd_ctx->lsm->u.enable.bytecode_len;
-
- if (bytecode_len > LTTNG_FILTER_MAX_LEN) {
- ret = LTTNG_ERR_FILTER_INVAL;
- free(exclusion);
- goto error;
- }
-
- bytecode = zmalloc(bytecode_len);
- if (!bytecode) {
- free(exclusion);
- ret = LTTNG_ERR_FILTER_NOMEM;
- goto error;
- }
-
- /* Receive var. len. data */
- DBG("Receiving var len filter's bytecode from client ...");
- ret = lttcomm_recv_unix_sock(sock, bytecode, bytecode_len);
- if (ret <= 0) {
- DBG("Nothing recv() from client car len data... continuing");
- *sock_error = 1;
- free(bytecode);
- free(exclusion);
- ret = LTTNG_ERR_FILTER_INVAL;
- goto error;
- }
-
- if ((bytecode->len + sizeof(*bytecode)) != bytecode_len) {
- free(bytecode);
- free(exclusion);
- ret = LTTNG_ERR_FILTER_INVAL;
- goto error;
- }
- }
-
- ret = cmd_enable_event(cmd_ctx->session, &cmd_ctx->lsm->domain,
- cmd_ctx->lsm->u.enable.channel_name,
- &cmd_ctx->lsm->u.enable.event,
- filter_expression, bytecode, exclusion,
- kernel_poll_pipe[1]);
- break;
- }
- case LTTNG_LIST_TRACEPOINTS:
- {
- struct lttng_event *events;
- ssize_t nb_events;
-
- session_lock_list();
- nb_events = cmd_list_tracepoints(cmd_ctx->lsm->domain.type, &events);
- session_unlock_list();
- 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;
-
- session_lock_list();
- nb_fields = cmd_list_tracepoint_fields(cmd_ctx->lsm->domain.type,
- &fields);
- session_unlock_list();
- 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_LIST_SYSCALLS:
- {
- struct lttng_event *events;
- ssize_t nb_events;
-
- nb_events = cmd_list_syscalls(&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_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, 0);
-
- 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) {
- free(domains);
- 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) {
- free(channels);
- 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) {
- free(events);
- 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_DATA_PENDING:
- {
- ret = cmd_data_pending(cmd_ctx->session);
- break;
- }
- case LTTNG_SNAPSHOT_ADD_OUTPUT:
- {
- struct lttcomm_lttng_output_id reply;
-
- ret = cmd_snapshot_add_output(cmd_ctx->session,
- &cmd_ctx->lsm->u.snapshot_output.output, &reply.id);
- if (ret != LTTNG_OK) {
- goto error;
- }
-
- ret = setup_lttng_msg(cmd_ctx, sizeof(reply));
- if (ret < 0) {
- goto setup_error;
- }
-
- /* Copy output list into message payload */
- memcpy(cmd_ctx->llm->payload, &reply, sizeof(reply));
- ret = LTTNG_OK;
- break;
- }
- case LTTNG_SNAPSHOT_DEL_OUTPUT:
- {
- ret = cmd_snapshot_del_output(cmd_ctx->session,
- &cmd_ctx->lsm->u.snapshot_output.output);
- break;
- }
- case LTTNG_SNAPSHOT_LIST_OUTPUT:
- {
- ssize_t nb_output;
- struct lttng_snapshot_output *outputs = NULL;
-
- nb_output = cmd_snapshot_list_outputs(cmd_ctx->session, &outputs);
- if (nb_output < 0) {
- ret = -nb_output;
- goto error;
- }
-
- ret = setup_lttng_msg(cmd_ctx,
- nb_output * sizeof(struct lttng_snapshot_output));
- if (ret < 0) {
- free(outputs);
- goto setup_error;
- }
-
- if (outputs) {
- /* Copy output list into message payload */
- memcpy(cmd_ctx->llm->payload, outputs,
- nb_output * sizeof(struct lttng_snapshot_output));
- free(outputs);
- }
-
- ret = LTTNG_OK;
- break;
- }
- case LTTNG_SNAPSHOT_RECORD:
- {
- ret = cmd_snapshot_record(cmd_ctx->session,
- &cmd_ctx->lsm->u.snapshot_record.output,
- cmd_ctx->lsm->u.snapshot_record.wait);
- break;
- }
- case LTTNG_CREATE_SESSION_SNAPSHOT:
- {
- 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_snapshot(cmd_ctx->lsm->session.name, uris,
- nb_uri, &cmd_ctx->creds);
- free(uris);
- break;
- }
- case LTTNG_CREATE_SESSION_LIVE:
- {
- 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, cmd_ctx->lsm->u.session_live.timer_interval);
- free(uris);
- break;
- }
- case LTTNG_SAVE_SESSION:
- {
- ret = cmd_save_sessions(&cmd_ctx->lsm->u.save_session.attr,
- &cmd_ctx->creds);
- 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 health_comm_msg msg;
- struct health_comm_reply reply;
-
- DBG("[thread] Manage health check started");
-
- rcu_register_thread();
-
- /* We might hit an error path before this is created. */
- lttng_poll_init(&events);
-
- /* 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;
- }
-
- if (is_root) {
- /* lttng health client socket path permissions */
- ret = chown(health_unix_sock_path, 0,
- utils_get_group_id(tracing_group_name));
- if (ret < 0) {
- ERR("Unable to set group on %s", health_unix_sock_path);
- PERROR("chown");
- ret = -1;
- goto error;
- }
-
- ret = chmod(health_unix_sock_path,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
- if (ret < 0) {
- ERR("Unable to set permissions on %s", health_unix_sock_path);
- PERROR("chmod");
- 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 = sessiond_set_thread_pollset(&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;
- }
-
- sessiond_notify_ready();
-
- while (1) {
- DBG("Health check ready");
-
- /* 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;
- }
-
- nb_fd = ret;
-
- 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 = sessiond_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();
-
- memset(&reply, 0, sizeof(reply));
- for (i = 0; i < NR_HEALTH_SESSIOND_TYPES; i++) {
- /*
- * health_check_state returns 0 if health is
- * bad.
- */
- if (!health_check_state(health_sessiond, i)) {
- reply.ret_code |= 1ULL << i;
- }
- }
-
- DBG2("Health check return value %" PRIx64, 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");
- }
- }
-
- 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");
-
- rcu_register_thread();
-
- health_register(health_sessiond, HEALTH_SESSIOND_TYPE_CMD);
-
- health_code_update();
-
- ret = lttcomm_listen_unix_sock(client_sock);
- if (ret < 0) {
- goto error_listen;
- }
-
- /*
- * Pass 2 as size here for the thread quit pipe and client_sock. 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, client_sock, LPOLLIN | LPOLLPRI);
- if (ret < 0) {
- goto error;
- }
-
- sessiond_notify_ready();
- ret = sem_post(&load_info->message_thread_ready);
- if (ret) {
- PERROR("sem_post message_thread_ready");
- goto error;
- }
-
- /* This testpoint is after we signal readiness to the parent. */
- if (testpoint(sessiond_thread_manage_clients)) {
- goto error;
- }
-
- if (testpoint(sessiond_thread_manage_clients_before_loop)) {
- goto error;
- }
-
- health_code_update();
-
- while (1) {
- DBG("Accepting client command ...");
-
- /* 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++) {
- /* Fetch once the poll data */
- revents = LTTNG_POLL_GETEV(&events, i);
- pollfd = LTTNG_POLL_GETFD(&events, i);
-
- health_code_update();
-
- /* 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 == client_sock) {
- if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
- ERR("Client socket poll error");
- goto error;
- }
- }
- }
-
- DBG("Wait for client response");
-
- health_code_update();
-
- sock = lttcomm_accept_unix_sock(client_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);
-
- /* Set socket option for credentials retrieval */
- ret = lttcomm_setsockopt_creds_unix_sock(sock);
- if (ret < 0) {
- goto error;
- }
-
- /* Allocate context command to process the client request */
- cmd_ctx = zmalloc(sizeof(struct command_ctx));
- if (cmd_ctx == NULL) {
- PERROR("zmalloc cmd_ctx");
- goto error;
- }
-
- /* Allocate data buffer for reception */
- cmd_ctx->lsm = zmalloc(sizeof(struct lttcomm_session_msg));
- if (cmd_ctx->lsm == NULL) {
- PERROR("zmalloc cmd_ctx->lsm");
- goto error;
- }
-
- cmd_ctx->llm = NULL;
- cmd_ctx->session = NULL;
-
- health_code_update();
-
- /*
- * Data is received from the lttng client. The struct
- * lttcomm_session_msg (lsm) contains the command and data request of
- * the client.
- */
- DBG("Receiving data from client ...");
- ret = lttcomm_recv_creds_unix_sock(sock, cmd_ctx->lsm,
- sizeof(struct lttcomm_session_msg), &cmd_ctx->creds);
- if (ret <= 0) {
- DBG("Nothing recv() from client... continuing");
- ret = close(sock);
- if (ret) {
- PERROR("close");
- }
- sock = -1;
- clean_command_ctx(&cmd_ctx);
- continue;
- }
-
- health_code_update();
-
- // TODO: Validate cmd_ctx including sanity check for
- // security purpose.
-
- rcu_thread_online();
- /*
- * This function dispatch the work to the kernel or userspace tracer
- * libs and fill the lttcomm_lttng_msg data structure of all the needed
- * informations for the client. The command context struct contains
- * everything this function may needs.
- */
- ret = process_client_msg(cmd_ctx, sock, &sock_error);
- rcu_thread_offline();
- if (ret < 0) {
- ret = close(sock);
- if (ret) {
- PERROR("close");
- }
- sock = -1;
- /*
- * TODO: Inform client somehow of the fatal error. At
- * this point, ret < 0 means that a zmalloc failed
- * (ENOMEM). Error detected but still accept
- * command, unless a socket error has been
- * detected.
- */
- clean_command_ctx(&cmd_ctx);
- continue;
- }
-
- health_code_update();
-
- DBG("Sending response (size: %d, retcode: %s)",
- cmd_ctx->lttng_msg_size,
- lttng_strerror(-cmd_ctx->llm->ret_code));
- ret = send_unix_sock(sock, cmd_ctx->llm, cmd_ctx->lttng_msg_size);
- if (ret < 0) {
- ERR("Failed to send data back to client");
- }
-
- /* End of transmission */
- ret = close(sock);
- if (ret) {
- PERROR("close");