X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fclient.c;h=fa7672b5834a370f3484ae43cb3d8f2306ba937a;hp=ea8ffd45fc066c3cfa16b4ac8017400361888e8d;hb=a914e76ac1a529191035f1fec439026c83beee3f;hpb=4ec029ed8d032ac98d8dc158a751841b7c150639 diff --git a/src/bin/lttng-sessiond/client.c b/src/bin/lttng-sessiond/client.c index ea8ffd45f..fa7672b58 100644 --- a/src/bin/lttng-sessiond/client.c +++ b/src/bin/lttng-sessiond/client.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "client.h" #include "lttng-sessiond.h" @@ -40,31 +42,28 @@ static bool is_root; static struct thread_state { - pthread_cond_t cond; - pthread_mutex_t lock; - bool is_running; -} thread_state = { - .cond = PTHREAD_COND_INITIALIZER, - .lock = PTHREAD_MUTEX_INITIALIZER, - .is_running = false -}; - -void set_thread_state_running(void) + sem_t ready; + bool running; +} thread_state; + +static void set_thread_status(bool running) { - pthread_mutex_lock(&thread_state.lock); - thread_state.is_running = true; - pthread_cond_broadcast(&thread_state.cond); - pthread_mutex_unlock(&thread_state.lock); + DBG("Marking client thread's state as %s", running ? "running" : "error"); + thread_state.running = running; + sem_post(&thread_state.ready); } -static void wait_thread_state_running(void) +static bool wait_thread_status(void) { - pthread_mutex_lock(&thread_state.lock); - while (!thread_state.is_running) { - pthread_cond_wait(&thread_state.cond, - &thread_state.lock); + DBG("Waiting for client thread to be ready"); + sem_wait(&thread_state.ready); + if (thread_state.running) { + DBG("Client thread is ready"); + } else { + ERR("Initialization of client thread failed"); } - pthread_mutex_unlock(&thread_state.lock); + + return thread_state.running; } /* @@ -84,6 +83,7 @@ static int setup_lttng_msg(struct command_ctx *cmd_ctx, const size_t payload_offset = cmd_header_offset + cmd_header_len; const size_t total_msg_size = header_len + cmd_header_len + payload_len; + free(cmd_ctx->llm); cmd_ctx->llm = zmalloc(total_msg_size); if (cmd_ctx->llm == NULL) { @@ -391,10 +391,13 @@ static int copy_session_consumer(int domain, struct ltt_session *session) } /* 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_strncpy(consumer->domain_subdir, dir_name, + sizeof(consumer->domain_subdir)); + if (ret) { + ret = LTTNG_ERR_UNK; + goto error; + } + DBG3("Copy session consumer subdir %s", consumer->domain_subdir); ret = LTTNG_OK; error: @@ -475,10 +478,10 @@ static int create_kernel_session(struct ltt_session *session) DBG("Creating kernel session"); - ret = kernel_create_session(session, kernel_tracer_fd); + ret = kernel_create_session(session); if (ret < 0) { ret = LTTNG_ERR_KERN_SESS_FAIL; - goto error; + goto error_create; } /* Code flow safety */ @@ -500,6 +503,7 @@ static int create_kernel_session(struct ltt_session *session) error: trace_kernel_destroy_session(session->kernel_session); session->kernel_session = NULL; +error_create: return ret; } @@ -702,10 +706,12 @@ static int send_unix_sock(int sock, void *buf, size_t len) * Return any error encountered or 0 for success. * * "sock" is only used for special-case var. len data. + * A command may assume the ownership of the socket, in which case its value + * should be set to -1. * * Should *NOT* be called with RCU read-side lock held. */ -static int process_client_msg(struct command_ctx *cmd_ctx, int sock, +static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_error) { int ret = LTTNG_OK; @@ -719,9 +725,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, *sock_error = 0; switch (cmd_ctx->lsm->cmd_type) { - case LTTNG_CREATE_SESSION: - case LTTNG_CREATE_SESSION_SNAPSHOT: - case LTTNG_CREATE_SESSION_LIVE: + case LTTNG_CREATE_SESSION_EXT: case LTTNG_DESTROY_SESSION: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_DOMAINS: @@ -799,9 +803,7 @@ 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_SNAPSHOT: - case LTTNG_CREATE_SESSION_LIVE: + case LTTNG_CREATE_SESSION_EXT: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: case LTTNG_LIST_SYSCALLS: @@ -877,6 +879,15 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, goto error; } + /* Kernel tracer check */ + if (!kernel_tracer_is_initialized()) { + /* Basically, load kernel tracer modules */ + ret = init_kernel_tracer(); + if (ret != 0) { + goto error; + } + } + /* Consumer is in an ERROR state. Report back to client */ if (uatomic_read(&kernel_consumerd_state) == CONSUMER_ERROR) { ret = LTTNG_ERR_NO_KERNCONSUMERD; @@ -887,7 +898,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, if (need_tracing_session) { if (cmd_ctx->session->kernel_session == NULL) { ret = create_kernel_session(cmd_ctx->session); - if (ret < 0) { + if (ret != LTTNG_OK) { ret = LTTNG_ERR_KERN_SESS_FAIL; goto error; } @@ -1108,13 +1119,13 @@ skip_domain: cmd_ctx->lsm->u.context.ctx.u.app_ctx.ctx_name = context_name; - ret = lttcomm_recv_unix_sock(sock, provider_name, + ret = lttcomm_recv_unix_sock(*sock, provider_name, provider_name_len); if (ret < 0) { goto error_add_context; } - ret = lttcomm_recv_unix_sock(sock, context_name, + ret = lttcomm_recv_unix_sock(*sock, context_name, context_name_len); if (ret < 0) { goto error_add_context; @@ -1167,7 +1178,7 @@ error_add_context: DBG("Discarding disable event command payload of size %zu", count); while (count) { - ret = lttcomm_recv_unix_sock(sock, data, + ret = lttcomm_recv_unix_sock(*sock, data, count > sizeof(data) ? sizeof(data) : count); if (ret < 0) { goto error; @@ -1225,7 +1236,7 @@ error_add_context: DBG("Receiving var len exclusion event list from client ..."); exclusion->count = count; - ret = lttcomm_recv_unix_sock(sock, exclusion->names, + 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"); @@ -1256,7 +1267,7 @@ error_add_context: /* Receive var. len. data */ DBG("Receiving var len filter's expression from client ..."); - ret = lttcomm_recv_unix_sock(sock, filter_expression, + ret = lttcomm_recv_unix_sock(*sock, filter_expression, expression_len); if (ret <= 0) { DBG("Nothing recv() from client var len data... continuing"); @@ -1289,7 +1300,7 @@ error_add_context: /* Receive var. len. data */ DBG("Receiving var len filter's bytecode from client ..."); - ret = lttcomm_recv_unix_sock(sock, bytecode, bytecode_len); + ret = lttcomm_recv_unix_sock(*sock, bytecode, bytecode_len); if (ret <= 0) { DBG("Nothing recv() from client var len data... continuing"); *sock_error = 1; @@ -1323,7 +1334,7 @@ error_add_context: if (cmd_ctx->lsm->u.enable.userspace_probe_location_len > 0) { /* Expect a userspace probe description. */ - ret = receive_userspace_probe(cmd_ctx, sock, sock_error, ev); + ret = receive_userspace_probe(cmd_ctx, *sock, sock_error, ev); if (ret) { free(filter_expression); free(bytecode); @@ -1476,7 +1487,7 @@ error_add_context: /* Receive variable len data */ DBG("Receiving %zu URI(s) from client ...", nb_uri); - ret = lttcomm_recv_unix_sock(sock, uris, len); + ret = lttcomm_recv_unix_sock(*sock, uris, len); if (ret <= 0) { DBG("No URIs received from client... continuing"); *sock_error = 1; @@ -1518,51 +1529,11 @@ error_add_context: 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, - notification_thread_handle); + notification_thread_handle, + sock); break; } case LTTNG_LIST_DOMAINS: @@ -1653,7 +1624,9 @@ error_add_context: nr_sessions = lttng_sessions_count( LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds)); - payload_len = sizeof(struct lttng_session) * nr_sessions; + + payload_len = (sizeof(struct lttng_session) * nr_sessions) + + (sizeof(struct lttng_session_extended) * nr_sessions); sessions_payload = zmalloc(payload_len); if (!sessions_payload) { @@ -1662,7 +1635,7 @@ error_add_context: goto setup_error; } - cmd_list_lttng_sessions(sessions_payload, + cmd_list_lttng_sessions(sessions_payload, nr_sessions, LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds)); session_unlock_list(); @@ -1739,13 +1712,15 @@ error_add_context: } case LTTNG_SNAPSHOT_ADD_OUTPUT: { + uint32_t snapshot_id; struct lttcomm_lttng_output_id reply; ret = cmd_snapshot_add_output(cmd_ctx->session, - &cmd_ctx->lsm->u.snapshot_output.output, &reply.id); + &cmd_ctx->lsm->u.snapshot_output.output, &snapshot_id); if (ret != LTTNG_OK) { goto error; } + reply.id = snapshot_id; ret = setup_lttng_msg_no_cmd_header(cmd_ctx, &reply, sizeof(reply)); @@ -1793,82 +1768,35 @@ error_add_context: cmd_ctx->lsm->u.snapshot_record.wait); break; } - case LTTNG_CREATE_SESSION_SNAPSHOT: + case LTTNG_CREATE_SESSION_EXT: { - size_t nb_uri, len; - struct lttng_uri *uris = NULL; + struct lttng_dynamic_buffer payload; + struct lttng_session_descriptor *return_descriptor = 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; - } + lttng_dynamic_buffer_init(&payload); + ret = cmd_create_session(cmd_ctx, *sock, &return_descriptor); + if (ret != LTTNG_OK) { + 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 = lttng_session_descriptor_serialize(return_descriptor, + &payload); + if (ret) { + ERR("Failed to serialize session descriptor in reply to \"create session\" command"); + lttng_session_descriptor_destroy(return_descriptor); + ret = LTTNG_ERR_NOMEM; + 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); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, payload.data, + payload.size); + if (ret) { + lttng_session_descriptor_destroy(return_descriptor); + ret = LTTNG_ERR_NOMEM; + goto error; + } + lttng_dynamic_buffer_reset(&payload); + lttng_session_descriptor_destroy(return_descriptor); + ret = LTTNG_OK; break; } case LTTNG_SAVE_SESSION: @@ -1895,13 +1823,13 @@ error_add_context: } case LTTNG_REGISTER_TRIGGER: { - ret = cmd_register_trigger(cmd_ctx, sock, + ret = cmd_register_trigger(cmd_ctx, *sock, notification_thread_handle); break; } case LTTNG_UNREGISTER_TRIGGER: { - ret = cmd_unregister_trigger(cmd_ctx, sock, + ret = cmd_unregister_trigger(cmd_ctx, *sock, notification_thread_handle); break; } @@ -1918,7 +1846,8 @@ error_add_context: goto error; } - ret = cmd_rotate_session(cmd_ctx->session, &rotate_return); + ret = cmd_rotate_session(cmd_ctx->session, &rotate_return, + false); if (ret < 0) { ret = -ret; goto error; @@ -2020,6 +1949,7 @@ setup_error: if (cmd_ctx->session) { session_unlock(cmd_ctx->session); session_put(cmd_ctx->session); + cmd_ctx->session = NULL; } if (need_tracing_session) { session_unlock_list(); @@ -2071,6 +2001,11 @@ static void cleanup_client_thread(void *data) lttng_pipe_destroy(quit_pipe); } +static void thread_init_cleanup(void *data) +{ + set_thread_status(false); +} + /* * This thread manage all clients request using the unix client socket for * communication. @@ -2090,6 +2025,7 @@ static void *thread_manage_clients(void *data) is_root = (getuid() == 0); + pthread_cleanup_push(thread_init_cleanup, NULL); client_sock = create_client_sock(); if (client_sock < 0) { goto error_listen; @@ -2127,6 +2063,10 @@ static void *thread_manage_clients(void *data) goto error; } + /* Set state as running. */ + set_thread_status(true); + pthread_cleanup_pop(0); + /* This testpoint is after we signal readiness to the parent. */ if (testpoint(sessiond_thread_manage_clients)) { goto error; @@ -2138,9 +2078,6 @@ static void *thread_manage_clients(void *data) health_code_update(); - /* Set state as running. */ - set_thread_state_running(); - while (1) { const struct cmd_completion_handler *cmd_completion_handler; @@ -2169,11 +2106,6 @@ static void *thread_manage_clients(void *data) health_code_update(); - if (!revents) { - /* No activity for this FD (poll implementation). */ - continue; - } - if (pollfd == thread_quit_pipe_fd) { err = 0; goto exit; @@ -2262,14 +2194,16 @@ static void *thread_manage_clients(void *data) * informations for the client. The command context struct contains * everything this function may needs. */ - ret = process_client_msg(cmd_ctx, sock, &sock_error); + ret = process_client_msg(cmd_ctx, &sock, &sock_error); rcu_thread_offline(); if (ret < 0) { - ret = close(sock); - if (ret) { - PERROR("close"); - } - sock = -1; + if (sock >= 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 @@ -2295,21 +2229,24 @@ static void *thread_manage_clients(void *data) health_code_update(); - DBG("Sending response (size: %d, retcode: %s (%d))", - cmd_ctx->lttng_msg_size, - lttng_strerror(-cmd_ctx->llm->ret_code), - 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"); - } + if (sock >= 0) { + DBG("Sending response (size: %d, retcode: %s (%d))", + cmd_ctx->lttng_msg_size, + lttng_strerror(-cmd_ctx->llm->ret_code), + 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"); - } - sock = -1; + /* End of transmission */ + ret = close(sock); + if (ret) { + PERROR("close"); + } + } + sock = -1; clean_command_ctx(&cmd_ctx); @@ -2362,9 +2299,11 @@ bool shutdown_client_thread(void *thread_data) struct lttng_thread *launch_client_thread(void) { + bool thread_running; struct lttng_pipe *client_quit_pipe; struct lttng_thread *thread; + sem_init(&thread_state.ready, 0, 0); client_quit_pipe = lttng_pipe_open(FD_CLOEXEC); if (!client_quit_pipe) { goto error; @@ -2383,8 +2322,11 @@ struct lttng_thread *launch_client_thread(void) * This thread is part of the threads that need to be fully * initialized before the session daemon is marked as "ready". */ - wait_thread_state_running(); - + thread_running = wait_thread_status(); + if (!thread_running) { + lttng_thread_put(thread); + thread = NULL; + } return thread; error: cleanup_client_thread(client_quit_pipe);