Fix: set session in output mode if URL are set afterwards
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index e9fa3b462d29d533583815296d3ed20c6723ce8e..c1f5a4e70b7ce83545ce0858db2f781b563fdc26 100644 (file)
@@ -462,9 +462,6 @@ static int init_kernel_tracing(struct ltt_kernel_session *session)
        if (session->consumer_fds_sent == 0 && session->consumer != NULL) {
                cds_lfht_for_each_entry(session->consumer->socks->ht, &iter.iter,
                                socket, node.node) {
-                       /* Code flow error */
-                       assert(socket->fd >= 0);
-
                        pthread_mutex_lock(socket->lock);
                        ret = kernel_consumer_send_session(socket, session);
                        pthread_mutex_unlock(socket->lock);
@@ -674,9 +671,6 @@ int cmd_setup_relayd(struct ltt_session *session)
                /* For each consumer socket, send relayd sockets */
                cds_lfht_for_each_entry(usess->consumer->socks->ht, &iter.iter,
                                socket, node.node) {
-                       /* Code flow error */
-                       assert(socket->fd >= 0);
-
                        pthread_mutex_lock(socket->lock);
                        ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session->id,
                                        usess->consumer, socket);
@@ -693,9 +687,6 @@ int cmd_setup_relayd(struct ltt_session *session)
                        && ksess->consumer->enabled) {
                cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter,
                                socket, node.node) {
-                       /* Code flow error */
-                       assert(socket->fd >= 0);
-
                        pthread_mutex_lock(socket->lock);
                        ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session->id,
                                        ksess->consumer, socket);
@@ -860,11 +851,12 @@ int cmd_enable_channel(struct ltt_session *session,
        rcu_read_lock();
 
        /*
-        * Don't try to enable a channel if the session has been started at
-        * some point in time before. The tracer does not allow it.
+        * The ringbuffer (both in user space and kernel) behave badly in overwrite
+        * mode and with less than 2 subbuf so block it right away and send back an
+        * invalid attribute error.
         */
-       if (session->started) {
-               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+       if (attr->attr.overwrite && attr->attr.num_subbuf < 2) {
+               ret = LTTNG_ERR_INVALID;
                goto error;
        }
 
@@ -876,6 +868,15 @@ int cmd_enable_channel(struct ltt_session *session,
                kchan = trace_kernel_get_channel_by_name(attr->name,
                                session->kernel_session);
                if (kchan == NULL) {
+                       /*
+                        * Don't try to create a channel if the session
+                        * has been started at some point in time
+                        * before. The tracer does not allow it.
+                        */
+                       if (session->started) {
+                               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+                               goto error;
+                       }
                        ret = channel_kernel_create(session->kernel_session, attr, wpipe);
                        if (attr->name[0] != '\0') {
                                session->kernel_session->has_non_default_channel = 1;
@@ -899,6 +900,15 @@ int cmd_enable_channel(struct ltt_session *session,
 
                uchan = trace_ust_find_channel_by_name(chan_ht, attr->name);
                if (uchan == NULL) {
+                       /*
+                        * Don't try to create a channel if the session
+                        * has been started at some point in time
+                        * before. The tracer does not allow it.
+                        */
+                       if (session->started) {
+                               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+                               goto error;
+                       }
                        ret = channel_ust_create(usess, attr, domain->buf_type);
                        if (attr->name[0] != '\0') {
                                usess->has_non_default_channel = 1;
@@ -1115,17 +1125,6 @@ int cmd_add_context(struct ltt_session *session, int domain,
        case LTTNG_DOMAIN_KERNEL:
                assert(session->kernel_session);
 
-               /*
-                * If a non-default channel has been created in the
-                * session, explicitely require that -c chan_name needs
-                * to be provided.
-                */
-               if (session->kernel_session->has_non_default_channel
-                               && channel_name[0] == '\0') {
-                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
-                       goto error;
-               }
-
                if (session->kernel_session->channel_count == 0) {
                        /* Create default channel */
                        ret = channel_kernel_create(session->kernel_session, NULL, kwpipe);
@@ -1147,16 +1146,6 @@ int cmd_add_context(struct ltt_session *session, int domain,
 
                assert(usess);
 
-               /*
-                * If a non-default channel has been created in the
-                * session, explicitely require that -c chan_name needs
-                * to be provided.
-                */
-               if (usess->has_non_default_channel && channel_name[0] == '\0') {
-                       ret = LTTNG_ERR_NEED_CHANNEL_NAME;
-                       goto error;
-               }
-
                chan_count = lttng_ht_get_count(usess->domain_global.channels);
                if (chan_count == 0) {
                        struct lttng_channel *attr;
@@ -1604,6 +1593,7 @@ error:
 int cmd_start_trace(struct ltt_session *session)
 {
        int ret;
+       unsigned long nb_chan = 0;
        struct ltt_kernel_session *ksession;
        struct ltt_ust_session *usess;
 
@@ -1619,6 +1609,21 @@ int cmd_start_trace(struct ltt_session *session)
                goto error;
        }
 
+       /*
+        * Starting a session without channel is useless since after that it's not
+        * possible to enable channel thus inform the client.
+        */
+       if (usess && usess->domain_global.channels) {
+               nb_chan += lttng_ht_get_count(usess->domain_global.channels);
+       }
+       if (ksession) {
+               nb_chan += ksession->channel_count;
+       }
+       if (!nb_chan) {
+               ret = LTTNG_ERR_NO_CHANNEL;
+               goto error;
+       }
+
        session->enabled = 1;
 
        /* Kernel tracing */
@@ -1774,6 +1779,17 @@ int cmd_set_consumer_uri(int domain, struct ltt_session *session,
                }
        }
 
+       /*
+        * Make sure to set the session in output mode after we set URI since a
+        * session can be created without URL (thus flagged in no output mode).
+        */
+       session->output_traces = 1;
+       if (ksess) {
+               ksess->output_traces = 1;
+       } else if (usess) {
+               usess->output_traces = 1;
+       }
+
        /* All good! */
        ret = LTTNG_OK;
 
@@ -1977,7 +1993,14 @@ int cmd_calibrate(int domain, struct lttng_calibrate *calibrate)
        {
                struct lttng_kernel_calibrate kcalibrate;
 
-               kcalibrate.type = calibrate->type;
+               switch (calibrate->type) {
+               case LTTNG_CALIBRATE_FUNCTION:
+               default:
+                       /* Default and only possible calibrate option. */
+                       kcalibrate.type = LTTNG_KERNEL_CALIBRATE_KRETPROBE;
+                       break;
+               }
+
                ret = kernel_calibrate(kernel_tracer_fd, &kcalibrate);
                if (ret < 0) {
                        ret = LTTNG_ERR_KERN_ENABLE_FAIL;
@@ -1989,7 +2012,14 @@ int cmd_calibrate(int domain, struct lttng_calibrate *calibrate)
        {
                struct lttng_ust_calibrate ucalibrate;
 
-               ucalibrate.type = calibrate->type;
+               switch (calibrate->type) {
+               case LTTNG_CALIBRATE_FUNCTION:
+               default:
+                       /* Default and only possible calibrate option. */
+                       ucalibrate.type = LTTNG_UST_CALIBRATE_TRACEPOINT;
+                       break;
+               }
+
                ret = ust_app_calibrate_glb(&ucalibrate);
                if (ret < 0) {
                        ret = LTTNG_ERR_UST_CALIBRATE_FAIL;
@@ -2039,13 +2069,15 @@ int cmd_register_consumer(struct ltt_session *session, int domain,
                        ret = LTTNG_ERR_CONNECT_FAIL;
                        goto error;
                }
+               cdata->cmd_sock = sock;
 
-               socket = consumer_allocate_socket(sock);
+               socket = consumer_allocate_socket(&cdata->cmd_sock);
                if (socket == NULL) {
                        ret = close(sock);
                        if (ret < 0) {
                                PERROR("close register consumer");
                        }
+                       cdata->cmd_sock = -1;
                        ret = LTTNG_ERR_FATAL;
                        goto error;
                }
@@ -2290,6 +2322,21 @@ int cmd_data_pending(struct ltt_session *session)
        if (session->enabled) {
                ret = LTTNG_ERR_SESSION_STARTED;
                goto error;
+       } else {
+               /*
+                * If stopped, just make sure we've started before else the above call
+                * will always send that there is data pending.
+                *
+                * The consumer assumes that when the data pending command is received,
+                * the trace has been started before or else no output data is written
+                * by the streams which is a condition for data pending. So, this is
+                * *VERY* important that we don't ask the consumer before a start
+                * trace.
+                */
+               if (!session->started) {
+                       ret = 0;
+                       goto error;
+               }
        }
 
        if (ksess && ksess->consumer) {
@@ -2589,13 +2636,7 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess,
        }
 
        ret = kernel_snapshot_record(ksess, output, wait, nb_streams);
-       if (ret < 0) {
-               if (ret == -EINVAL) {
-                       ret = LTTNG_ERR_INVALID;
-                       goto error_snapshot;
-               }
-
-               ret = LTTNG_ERR_SNAPSHOT_FAIL;
+       if (ret != LTTNG_OK) {
                goto error_snapshot;
        }
 
@@ -2648,12 +2689,17 @@ static int record_ust_snapshot(struct ltt_ust_session *usess,
 
        ret = ust_app_snapshot_record(usess, output, wait, nb_streams);
        if (ret < 0) {
-               if (ret == -EINVAL) {
+               switch (-ret) {
+               case EINVAL:
                        ret = LTTNG_ERR_INVALID;
-                       goto error_snapshot;
+                       break;
+               case ENODATA:
+                       ret = LTTNG_ERR_SNAPSHOT_NODATA;
+                       break;
+               default:
+                       ret = LTTNG_ERR_SNAPSHOT_FAIL;
+                       break;
                }
-
-               ret = LTTNG_ERR_SNAPSHOT_FAIL;
                goto error_snapshot;
        }
 
@@ -2848,6 +2894,8 @@ int cmd_snapshot_record(struct ltt_session *session,
 
        if (snapshot_success) {
                session->snapshot.nb_snapshot++;
+       } else {
+               ret = LTTNG_ERR_SNAPSHOT_FAIL;
        }
 
 error:
This page took 0.027375 seconds and 4 git commands to generate.