Fix: use off_t type for lseek function return value to avoid overflow
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index 325ffd2cf14f6ec3e320e402e8db17a6dac71adc..bb46093e2586f4f458d60ad2584f7c97d264c0d3 100644 (file)
@@ -235,11 +235,11 @@ end:
 /*
  * Fill lttng_channel array of all channels.
  */
-static void list_lttng_channels(enum lttng_domain_type domain,
+static ssize_t list_lttng_channels(enum lttng_domain_type domain,
                struct ltt_session *session, struct lttng_channel *channels,
                struct lttcomm_channel_extended *chan_exts)
 {
-       int i = 0, ret;
+       int i = 0, ret = 0;
        struct ltt_kernel_channel *kchan;
 
        DBG("Listing channels for session %s", session->name);
@@ -325,7 +325,11 @@ static void list_lttng_channels(enum lttng_domain_type domain,
        }
 
 end:
-       return;
+       if (ret < 0) {
+               return -LTTNG_ERR_FATAL;
+       } else {
+               return LTTNG_OK;
+       }
 }
 
 static void increment_extended_len(const char *filter_expression,
@@ -852,8 +856,11 @@ static int create_connect_relayd(struct lttng_uri *uri,
 
                /* Check relayd version */
                ret = relayd_version_check(rsock);
-               if (ret < 0) {
-                       ret = LTTNG_ERR_RELAYD_VERSION_FAIL;
+               if (ret == LTTNG_ERR_RELAYD_VERSION_FAIL) {
+                       goto close_sock;
+               } else if (ret < 0) {
+                       ERR("Unable to reach lttng-relayd");
+                       ret = LTTNG_ERR_RELAYD_CONNECT_FAIL;
                        goto close_sock;
                }
                consumer->relay_major_version = rsock->major;
@@ -882,6 +889,8 @@ error:
 
 /*
  * Connect to the relayd using URI and send the socket to the right consumer.
+ *
+ * The consumer socket lock must be held by the caller.
  */
 static int send_consumer_relayd_socket(enum lttng_domain_type domain,
                unsigned int session_id, struct lttng_uri *relayd_uri,
@@ -895,7 +904,7 @@ static int send_consumer_relayd_socket(enum lttng_domain_type domain,
        /* Connect to relayd and make version check if uri is the control. */
        ret = create_connect_relayd(relayd_uri, &rsock, consumer);
        if (ret != LTTNG_OK) {
-               goto error;
+               goto relayd_comm_error;
        }
        assert(rsock);
 
@@ -935,10 +944,6 @@ static int send_consumer_relayd_socket(enum lttng_domain_type domain,
         */
 
 close_sock:
-       (void) relayd_close(rsock);
-       free(rsock);
-
-error:
        if (ret != LTTNG_OK) {
                /*
                 * The consumer output for this session should not be used anymore
@@ -947,6 +952,10 @@ error:
                 */
                consumer->enabled = 0;
        }
+       (void) relayd_close(rsock);
+       free(rsock);
+
+relayd_comm_error:
        return ret;
 }
 
@@ -954,6 +963,8 @@ error:
  * Send both relayd sockets to a specific consumer and domain.  This is a
  * helper function to facilitate sending the information to the consumer for a
  * session.
+ *
+ * The consumer socket lock must be held by the caller.
  */
 static int send_consumer_relayd_sockets(enum lttng_domain_type domain,
                unsigned int session_id, struct consumer_output *consumer,
@@ -1605,6 +1616,16 @@ int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain,
        int ret, chan_kern_created = 0, chan_ust_created = 0;
        char *app_ctx_provider_name = NULL, *app_ctx_name = NULL;
 
+       /*
+        * Don't try to add a context if the session has been started at
+        * some point in time before. The tracer does not allow it and would
+        * result in a corrupted trace.
+        */
+       if (session->has_been_started) {
+               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+               goto end;
+       }
+
        if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
                app_ctx_provider_name = ctx->u.app_ctx.provider_name;
                app_ctx_name = ctx->u.app_ctx.ctx_name;
@@ -2952,7 +2973,12 @@ ssize_t cmd_list_channels(enum lttng_domain_type domain,
 
                channel_exts = ((void *) *channels) +
                                (nb_chan * sizeof(struct lttng_channel));
-               list_lttng_channels(domain, session, *channels, channel_exts);
+               ret = list_lttng_channels(domain, session, *channels, channel_exts);
+               if (ret != LTTNG_OK) {
+                       free(*channels);
+                       *channels = NULL;
+                       goto end;
+               }
        } else {
                *channels = NULL;
        }
@@ -3377,6 +3403,29 @@ end:
        return ret;
 }
 
+static
+int clear_metadata_file(int fd)
+{
+       int ret;
+       off_t lseek_ret;
+
+       lseek_ret = lseek(fd, 0, SEEK_SET);
+       if (lseek_ret < 0) {
+               PERROR("lseek");
+               ret = -1;
+               goto end;
+       }
+
+       ret = ftruncate(fd, 0);
+       if (ret < 0) {
+               PERROR("ftruncate");
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
 static
 int ust_regenerate_metadata(struct ltt_ust_session *usess)
 {
@@ -3398,6 +3447,15 @@ int ust_regenerate_metadata(struct ltt_ust_session *usess)
                memset(registry->metadata, 0, registry->metadata_alloc_len);
                registry->metadata_len = 0;
                registry->metadata_version++;
+               if (registry->metadata_fd > 0) {
+                       /* Clear the metadata file's content. */
+                       ret = clear_metadata_file(registry->metadata_fd);
+                       if (ret) {
+                               pthread_mutex_unlock(&registry->lock);
+                               goto end;
+                       }
+               }
+
                ret = ust_metadata_session_statedump(registry, NULL,
                                registry->major, registry->minor);
                if (ret) {
@@ -3567,10 +3625,12 @@ static int set_relayd_for_snapshot(struct consumer_output *consumer,
        rcu_read_lock();
        cds_lfht_for_each_entry(snap_output->consumer->socks->ht, &iter.iter,
                        socket, node.node) {
+               pthread_mutex_lock(socket->lock);
                ret = send_consumer_relayd_sockets(0, session->id,
                                snap_output->consumer, socket,
                                session->name, session->hostname,
                                session->live_timer);
+               pthread_mutex_unlock(socket->lock);
                if (ret != LTTNG_OK) {
                        rcu_read_unlock();
                        goto error;
This page took 0.03736 seconds and 4 git commands to generate.