- /* 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_ENABLE_EVENT_WITH_FILTER:
- {
- struct lttng_filter_bytecode *bytecode;
-
- if (cmd_ctx->lsm->u.enable.bytecode_len > LTTNG_FILTER_MAX_LEN) {
- ret = LTTNG_ERR_FILTER_INVAL;
- goto error;
- }
- if (cmd_ctx->lsm->u.enable.bytecode_len == 0) {
- ret = LTTNG_ERR_FILTER_INVAL;
- goto error;
- }
- bytecode = zmalloc(cmd_ctx->lsm->u.enable.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.enable.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.enable.bytecode_len) {
- free(bytecode);
- 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, bytecode, NULL, kernel_poll_pipe[1]);
- 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;
- }
- 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;
- }
-
- 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();
-
- reply.ret_code = 0;
- 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);
-
- if (testpoint(thread_manage_clients)) {
- goto error_testpoint;
- }
-
- 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;
- }
-
- /*
- * Notify parent pid that we are ready to accept command for client side.
- * This ppid is the one from the external process that spawned us.
- */
- if (opt_sig_parent) {
- kill(ppid, SIGUSR1);
- }
-
- /* Notify the parent of the fork() process that we are ready. */
- if (opt_daemon) {
- kill(child_ppid, SIGUSR1);
- }
-
- if (testpoint(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;