Fix: add-context cannot be performed after a session has been started
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index 7b9647436ac82e059fdc61aa7216ddbbe9ca9dfc..1a3c22a6c8f87715dc85c878ec5b0c3443d7d1e3 100644 (file)
@@ -34,7 +34,9 @@
 #include <lttng/trigger/trigger-internal.h>
 #include <lttng/condition/condition.h>
 #include <lttng/action/action.h>
+#include <lttng/channel.h>
 #include <lttng/channel-internal.h>
+#include <common/string-utils/string-utils.h>
 
 #include "channel.h"
 #include "consumer.h"
@@ -61,7 +63,6 @@
 static pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER;
 static uint64_t relayd_net_seq_idx;
 
-static int validate_event_name(const char *);
 static int validate_ust_event_name(const char *);
 static int cmd_enable_event_internal(struct ltt_session *session,
                struct lttng_domain *domain,
@@ -243,11 +244,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 lttng_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);
@@ -277,6 +278,7 @@ static void list_lttng_channels(enum lttng_domain_type domain,
                                chan_exts[i].lost_packets = lost_packets;
                                chan_exts[i].monitor_timer_interval =
                                                extended->monitor_timer_interval;
+                               chan_exts[i].blocking_timeout = 0;
                                i++;
                        }
                }
@@ -322,6 +324,11 @@ static void list_lttng_channels(enum lttng_domain_type domain,
                                break;
                        }
 
+                       chan_exts[i].monitor_timer_interval =
+                                       uchan->monitor_timer_interval;
+                       chan_exts[i].blocking_timeout =
+                               uchan->attr.u.s.blocking_timeout;
+
                        ret = get_ust_runtime_stats(session, uchan,
                                        &discarded_events, &lost_packets);
                        if (ret < 0) {
@@ -329,8 +336,6 @@ static void list_lttng_channels(enum lttng_domain_type domain,
                        }
                        chan_exts[i].discarded_events = discarded_events;
                        chan_exts[i].lost_packets = lost_packets;
-                       chan_exts[i].monitor_timer_interval =
-                                       uchan->monitor_timer_interval;
                        i++;
                }
                rcu_read_unlock();
@@ -341,7 +346,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,
@@ -898,6 +907,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,
@@ -911,7 +922,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);
 
@@ -951,10 +962,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
@@ -963,6 +970,10 @@ error:
                 */
                consumer->enabled = 0;
        }
+       (void) relayd_close(rsock);
+       free(rsock);
+
+relayd_comm_error:
        return ret;
 }
 
@@ -970,6 +981,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,
@@ -1349,6 +1362,30 @@ int cmd_enable_channel(struct ltt_session *session,
                attr->attr.switch_timer_interval = 0;
        }
 
+       /* Check for feature support */
+       switch (domain->type) {
+       case LTTNG_DOMAIN_KERNEL:
+       {
+               if (kernel_supports_ring_buffer_snapshot_sample_positions(kernel_tracer_fd) != 1) {
+                       /* Sampling position of buffer is not supported */
+                       WARN("Kernel tracer does not support buffer monitoring. "
+                                       "Setting the monitor interval timer to 0 "
+                                       "(disabled) for channel '%s' of session '%s'",
+                                       attr-> name, session->name);
+                       lttng_channel_set_monitor_timer_interval(attr, 0);
+               }
+               break;
+       }
+       case LTTNG_DOMAIN_UST:
+       case LTTNG_DOMAIN_JUL:
+       case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_PYTHON:
+               break;
+       default:
+               ret = LTTNG_ERR_UNKNOWN_DOMAIN;
+               goto error;
+       }
+
        switch (domain->type) {
        case LTTNG_DOMAIN_KERNEL:
        {
@@ -1444,10 +1481,6 @@ int cmd_disable_event(struct ltt_session *session,
        DBG("Disable event command for event \'%s\'", event->name);
 
        event_name = event->name;
-       if (validate_event_name(event_name)) {
-               ret = LTTNG_ERR_INVALID_EVENT_NAME;
-               goto error;
-       }
 
        /* Error out on unhandled search criteria */
        if (event->loglevel_type || event->loglevel != -1 || event->enabled
@@ -1621,6 +1654,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;
@@ -1739,43 +1782,6 @@ end:
        return ret;
 }
 
-static int validate_event_name(const char *name)
-{
-       int ret = 0;
-       const char *c = name;
-       const char *event_name_end = c + LTTNG_SYMBOL_NAME_LEN;
-       bool null_terminated = false;
-
-       /*
-        * Make sure that unescaped wildcards are only used as the last
-        * character of the event name.
-        */
-       while (c < event_name_end) {
-               switch (*c) {
-               case '\0':
-                       null_terminated = true;
-                       goto end;
-               case '\\':
-                       c++;
-                       break;
-               case '*':
-                       if ((c + 1) < event_name_end && *(c + 1)) {
-                               /* Wildcard is not the last character */
-                               ret = LTTNG_ERR_INVALID_EVENT_NAME;
-                               goto end;
-                       }
-               default:
-                       break;
-               }
-               c++;
-       }
-end:
-       if (!ret && !null_terminated) {
-               ret = LTTNG_ERR_INVALID_EVENT_NAME;
-       }
-       return ret;
-}
-
 static inline bool name_starts_with(const char *name, const char *prefix)
 {
        const size_t max_cmp_len = min(strlen(prefix), LTTNG_SYMBOL_NAME_LEN);
@@ -1821,7 +1827,7 @@ static int _cmd_enable_event(struct ltt_session *session,
                struct lttng_event_exclusion *exclusion,
                int wpipe, bool internal_event)
 {
-       int ret, channel_created = 0;
+       int ret = 0, channel_created = 0;
        struct lttng_channel *attr = NULL;
 
        assert(session);
@@ -1831,15 +1837,24 @@ static int _cmd_enable_event(struct ltt_session *session,
        /* If we have a filter, we must have its filter expression */
        assert(!(!!filter_expression ^ !!filter));
 
-       DBG("Enable event command for event \'%s\'", event->name);
+       /* Normalize event name as a globbing pattern */
+       strutils_normalize_star_glob_pattern(event->name);
 
-       rcu_read_lock();
+       /* Normalize exclusion names as globbing patterns */
+       if (exclusion) {
+               size_t i;
 
-       ret = validate_event_name(event->name);
-       if (ret) {
-               goto error;
+               for (i = 0; i < exclusion->count; i++) {
+                       char *name = LTTNG_EVENT_EXCLUSION_NAME_AT(exclusion, i);
+
+                       strutils_normalize_star_glob_pattern(name);
+               }
        }
 
+       DBG("Enable event command for event \'%s\'", event->name);
+
+       rcu_read_lock();
+
        switch (domain->type) {
        case LTTNG_DOMAIN_KERNEL:
        {
@@ -2968,7 +2983,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;
        }
@@ -3544,7 +3564,6 @@ int cmd_regenerate_statedump(struct ltt_session *session)
                ret = LTTNG_ERR_SESSION_NOT_STARTED;
                goto end;
        }
-       ret = 0;
 
        if (session->kernel_session) {
                ret = kernctl_session_regenerate_statedump(
@@ -3619,7 +3638,10 @@ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock,
 
        ret = notification_thread_command_register_trigger(notification_thread,
                        trigger);
+       /* Ownership of trigger was transferred. */
+       trigger = NULL;
 end:
+       lttng_trigger_destroy(trigger);
        lttng_dynamic_buffer_reset(&trigger_buffer);
        return ret;
 }
@@ -3662,6 +3684,7 @@ int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock,
        ret = notification_thread_command_unregister_trigger(notification_thread,
                        trigger);
 end:
+       lttng_trigger_destroy(trigger);
        lttng_dynamic_buffer_reset(&trigger_buffer);
        return ret;
 }
@@ -3697,10 +3720,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.027483 seconds and 4 git commands to generate.