Fix: don't hide EBADF error subbuffer write
[lttng-tools.git] / src / bin / lttng-sessiond / client.c
index ea8ffd45fc066c3cfa16b4ac8017400361888e8d..4565a18c31efe55f70e94293cd03d6962d574af4 100644 (file)
@@ -26,6 +26,8 @@
 #include <common/utils.h>
 #include <lttng/userspace-probe-internal.h>
 #include <lttng/event-internal.h>
+#include <lttng/session-internal.h>
+#include <lttng/session-descriptor-internal.h>
 
 #include "client.h"
 #include "lttng-sessiond.h"
 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:
@@ -478,7 +481,7 @@ static int create_kernel_session(struct ltt_session *session)
        ret = kernel_create_session(session, kernel_tracer_fd);
        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;
 }
 
@@ -719,9 +723,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 +801,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:
@@ -887,7 +887,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;
                                }
@@ -1518,47 +1518,6 @@ 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,
@@ -1653,7 +1612,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 +1623,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();
@@ -1793,82 +1754,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;
-
-               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;
-                       }
+               struct lttng_dynamic_buffer payload;
+               struct lttng_session_descriptor *return_descriptor = NULL;
 
-                       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:
@@ -2071,6 +1985,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 +2009,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 +2047,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 +2062,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 +2090,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;
@@ -2362,9 +2278,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 +2301,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);
This page took 0.027639 seconds and 4 git commands to generate.