CUSTOM: liver timer: immediate liver timer control on data pending and destroy
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index 3c59d092c2e9b0f2ca848277219091307b20c078..8cb60b3aa51d2ace2f7efaea0375e809cf78dbed 100644 (file)
@@ -41,6 +41,7 @@
 #include "syscall.h"
 #include "agent.h"
 #include "buffer-registry.h"
+#include "agent-thread.h"
 
 #include "cmd.h"
 
@@ -235,11 +236,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);
@@ -277,7 +278,10 @@ static void list_lttng_channels(enum lttng_domain_type domain,
                                &iter.iter, uchan, node.node) {
                        uint64_t discarded_events = 0, lost_packets = 0;
 
-                       strncpy(channels[i].name, uchan->name, LTTNG_SYMBOL_NAME_LEN);
+                       if (lttng_strncpy(channels[i].name, uchan->name,
+                                       LTTNG_SYMBOL_NAME_LEN)) {
+                               break;
+                       }
                        channels[i].attr.overwrite = uchan->attr.overwrite;
                        channels[i].attr.subbuf_size = uchan->attr.subbuf_size;
                        channels[i].attr.num_subbuf = uchan->attr.num_subbuf;
@@ -322,7 +326,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,
@@ -849,8 +857,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;
@@ -879,6 +890,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,
@@ -892,7 +905,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);
 
@@ -932,10 +945,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
@@ -944,6 +953,10 @@ error:
                 */
                consumer->enabled = 0;
        }
+       (void) relayd_close(rsock);
+       free(rsock);
+
+relayd_comm_error:
        return ret;
 }
 
@@ -951,6 +964,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,
@@ -1180,12 +1195,14 @@ error:
 }
 
 /*
- * Command LTTNG_TRACK_PID processed by the client thread.
+ * Command LTTNG_TRACK_ID processed by the client thread.
  *
  * Called with session lock held.
  */
-int cmd_track_pid(struct ltt_session *session, enum lttng_domain_type domain,
-               int pid)
+int cmd_track_id(struct ltt_session *session,
+               enum lttng_tracker_type tracker_type,
+               enum lttng_domain_type domain,
+               struct lttng_tracker_id *id)
 {
        int ret;
 
@@ -1198,7 +1215,7 @@ int cmd_track_pid(struct ltt_session *session, enum lttng_domain_type domain,
 
                ksess = session->kernel_session;
 
-               ret = kernel_track_pid(ksess, pid);
+               ret = kernel_track_id(tracker_type, ksess, id);
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -1212,7 +1229,7 @@ int cmd_track_pid(struct ltt_session *session, enum lttng_domain_type domain,
 
                usess = session->ust_session;
 
-               ret = trace_ust_track_pid(usess, pid);
+               ret = trace_ust_track_id(tracker_type, usess, id);
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -1231,12 +1248,14 @@ error:
 }
 
 /*
- * Command LTTNG_UNTRACK_PID processed by the client thread.
+ * Command LTTNG_UNTRACK_ID processed by the client thread.
  *
  * Called with session lock held.
  */
-int cmd_untrack_pid(struct ltt_session *session, enum lttng_domain_type domain,
-               int pid)
+int cmd_untrack_id(struct ltt_session *session,
+               enum lttng_tracker_type tracker_type,
+               enum lttng_domain_type domain,
+               struct lttng_tracker_id *id)
 {
        int ret;
 
@@ -1249,7 +1268,7 @@ int cmd_untrack_pid(struct ltt_session *session, enum lttng_domain_type domain,
 
                ksess = session->kernel_session;
 
-               ret = kernel_untrack_pid(ksess, pid);
+               ret = kernel_untrack_id(tracker_type, ksess, id);
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -1263,7 +1282,7 @@ int cmd_untrack_pid(struct ltt_session *session, enum lttng_domain_type domain,
 
                usess = session->ust_session;
 
-               ret = trace_ust_untrack_pid(usess, pid);
+               ret = trace_ust_untrack_id(tracker_type, usess, id);
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -1330,14 +1349,19 @@ int cmd_enable_channel(struct ltt_session *session,
                attr->attr.switch_timer_interval = 0;
        }
 
-       /*
-        * 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 (attr->attr.overwrite && attr->attr.num_subbuf < 2) {
-               ret = LTTNG_ERR_INVALID;
-               goto error;
+       /* Check for feature support */
+       switch (domain->type) {
+       case LTTNG_DOMAIN_JUL:
+       case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_PYTHON:
+               if (!agent_tracing_is_enabled()) {
+                       DBG("Attempted to enable a channel in an agent domain but the agent thread is not running");
+                       ret = LTTNG_ERR_AGENT_TRACING_DISABLED;
+                       goto error;
+               }
+               break;
+       default:
+               break;
        }
 
        switch (domain->type) {
@@ -1612,6 +1636,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;
@@ -2063,6 +2097,12 @@ static int _cmd_enable_event(struct ltt_session *session,
 
                assert(usess);
 
+               if (!agent_tracing_is_enabled()) {
+                       DBG("Attempted to enable an event in an agent domain but the agent thread is not running");
+                       ret = LTTNG_ERR_AGENT_TRACING_DISABLED;
+                       goto error;
+               }
+
                agt = trace_ust_find_agent(usess, domain->type);
                if (!agt) {
                        agt = agent_create(domain->type);
@@ -2296,12 +2336,14 @@ ssize_t cmd_list_syscalls(struct lttng_event **events)
 }
 
 /*
- * Command LTTNG_LIST_TRACKER_PIDS processed by the client thread.
+ * Command LTTNG_LIST_TRACKER_IDS processed by the client thread.
  *
  * Called with session lock held.
  */
-ssize_t cmd_list_tracker_pids(struct ltt_session *session,
-               enum lttng_domain_type domain, int32_t **pids)
+ssize_t cmd_list_tracker_ids(enum lttng_tracker_type tracker_type,
+               struct ltt_session *session,
+               enum lttng_domain_type domain,
+               struct lttng_tracker_id **ids)
 {
        int ret;
        ssize_t nr_pids = 0;
@@ -2312,7 +2354,7 @@ ssize_t cmd_list_tracker_pids(struct ltt_session *session,
                struct ltt_kernel_session *ksess;
 
                ksess = session->kernel_session;
-               nr_pids = kernel_list_tracker_pids(ksess, pids);
+               nr_pids = kernel_list_tracker_ids(tracker_type, ksess, ids);
                if (nr_pids < 0) {
                        ret = LTTNG_ERR_KERN_LIST_FAIL;
                        goto error;
@@ -2324,7 +2366,7 @@ ssize_t cmd_list_tracker_pids(struct ltt_session *session,
                struct ltt_ust_session *usess;
 
                usess = session->ust_session;
-               nr_pids = trace_ust_list_tracker_pids(usess, pids);
+               nr_pids = trace_ust_list_tracker_ids(tracker_type, usess, ids);
                if (nr_pids < 0) {
                        ret = LTTNG_ERR_UST_LIST_FAIL;
                        goto error;
@@ -2444,7 +2486,15 @@ int cmd_stop_trace(struct ltt_session *session)
        if (ksession && ksession->active) {
                DBG("Stop kernel tracing");
 
-               /* Flush metadata if exist */
+               ret = kernel_stop_session(ksession);
+               if (ret < 0) {
+                       ret = LTTNG_ERR_KERN_STOP_FAIL;
+                       goto error;
+               }
+
+               kernel_wait_quiescent(kernel_tracer_fd);
+
+               /* Flush metadata after stopping (if exists) */
                if (ksession->metadata_stream_fd >= 0) {
                        ret = kernel_metadata_flush_buffer(ksession->metadata_stream_fd);
                        if (ret < 0) {
@@ -2452,7 +2502,7 @@ int cmd_stop_trace(struct ltt_session *session)
                        }
                }
 
-               /* Flush all buffers before stopping */
+               /* Flush all buffers after stopping */
                cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) {
                        ret = kernel_flush_buffer(kchan);
                        if (ret < 0) {
@@ -2460,14 +2510,6 @@ int cmd_stop_trace(struct ltt_session *session)
                        }
                }
 
-               ret = kernel_stop_session(ksession);
-               if (ret < 0) {
-                       ret = LTTNG_ERR_KERN_STOP_FAIL;
-                       goto error;
-               }
-
-               kernel_wait_quiescent(kernel_tracer_fd);
-
                ksession->active = 0;
        }
 
@@ -2731,6 +2773,8 @@ int cmd_destroy_session(struct ltt_session *session, int wpipe)
                /* Close any relayd session */
                consumer_output_send_destroy_relayd(usess->consumer);
 
+               ust_force_stop_live_timer(usess);
+
                /* Destroy every UST application related to this session. */
                ret = ust_app_destroy_trace_all(usess);
                if (ret) {
@@ -2755,64 +2799,6 @@ int cmd_destroy_session(struct ltt_session *session, int wpipe)
        return ret;
 }
 
-/*
- * Command LTTNG_CALIBRATE processed by the client thread.
- */
-int cmd_calibrate(enum lttng_domain_type domain,
-               struct lttng_calibrate *calibrate)
-{
-       int ret;
-
-       switch (domain) {
-       case LTTNG_DOMAIN_KERNEL:
-       {
-               struct lttng_kernel_calibrate kcalibrate;
-
-               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;
-                       goto error;
-               }
-               break;
-       }
-       case LTTNG_DOMAIN_UST:
-       {
-               struct lttng_ust_calibrate ucalibrate;
-
-               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;
-                       goto error;
-               }
-               break;
-       }
-       default:
-               ret = LTTNG_ERR_UND;
-               goto error;
-       }
-
-       ret = LTTNG_OK;
-
-error:
-       return ret;
-}
-
 /*
  * Command LTTNG_REGISTER_CONSUMER processed by the client thread.
  */
@@ -3017,7 +3003,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;
        }
@@ -3183,11 +3174,21 @@ int cmd_data_pending(struct ltt_session *session)
        }
 
        if (usess && usess->consumer) {
+               /*
+                * Stop the live timer since it can lead to stream and relayd
+                * contention for the data pending check.
+                */
+               ust_force_stop_live_timer(usess);
                ret = consumer_is_data_pending(usess->id, usess->consumer);
                if (ret == 1) {
                        /* Data is still being extracted for the kernel. */
                        goto error;
                }
+               /*
+                * Restart the live timer to ensure that we send inactivity
+                * beacon as needed
+                */
+               ust_force_start_live_timer(usess);
        }
 
        /* Data is ready to be read by a viewer */
@@ -3214,11 +3215,10 @@ int cmd_snapshot_add_output(struct ltt_session *session,
        DBG("Cmd snapshot add output for session %s", session->name);
 
        /*
-        * Permission denied to create an output if the session is not
-        * set in no output mode.
+        * Can't create an output if the session is not set in no-output mode.
         */
        if (session->output_traces) {
-               ret = LTTNG_ERR_EPERM;
+               ret = LTTNG_ERR_NOT_SNAPSHOT_SESSION;
                goto error;
        }
 
@@ -3282,7 +3282,7 @@ int cmd_snapshot_del_output(struct ltt_session *session,
         * set in no output mode.
         */
        if (session->output_traces) {
-               ret = LTTNG_ERR_EPERM;
+               ret = LTTNG_ERR_NOT_SNAPSHOT_SESSION;
                goto error;
        }
 
@@ -3334,19 +3334,19 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session,
         * set in no output mode.
         */
        if (session->output_traces) {
-               ret = -LTTNG_ERR_EPERM;
-               goto error;
+               ret = -LTTNG_ERR_NOT_SNAPSHOT_SESSION;
+               goto end;
        }
 
        if (session->snapshot.nb_output == 0) {
                ret = 0;
-               goto error;
+               goto end;
        }
 
        list = zmalloc(session->snapshot.nb_output * sizeof(*list));
        if (!list) {
                ret = -LTTNG_ERR_NOMEM;
-               goto error;
+               goto end;
        }
 
        /* Copy list from session to the new list object. */
@@ -3392,8 +3392,9 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session,
        list = NULL;
        ret = session->snapshot.nb_output;
 error:
-       free(list);
        rcu_read_unlock();
+       free(list);
+end:
        return ret;
 }
 
@@ -3404,7 +3405,7 @@ error:
  * Return 0 if the metadata can be generated, a LTTNG_ERR code otherwise.
  */
 static
-int check_metadata_regenerate_support(struct ltt_session *session)
+int check_regenerate_metadata_support(struct ltt_session *session)
 {
        int ret;
 
@@ -3443,7 +3444,30 @@ end:
 }
 
 static
-int ust_metadata_regenerate(struct ltt_ust_session *usess)
+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)
 {
        int ret = 0;
        struct buffer_reg_uid *uid_reg = NULL;
@@ -3463,6 +3487,15 @@ int ust_metadata_regenerate(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) {
@@ -3504,7 +3537,7 @@ end:
 }
 
 /*
- * Command LTTNG_METADATA_REGENERATE from the lttng-ctl library.
+ * Command LTTNG_REGENERATE_METADATA from the lttng-ctl library.
  *
  * Ask the consumer to truncate the existing metadata file(s) and
  * then regenerate the metadata. Live and per-pid sessions are not
@@ -3512,19 +3545,19 @@ end:
  *
  * Return 0 on success or else a LTTNG_ERR code.
  */
-int cmd_metadata_regenerate(struct ltt_session *session)
+int cmd_regenerate_metadata(struct ltt_session *session)
 {
        int ret;
 
        assert(session);
 
-       ret = check_metadata_regenerate_support(session);
+       ret = check_regenerate_metadata_support(session);
        if (ret) {
                goto end;
        }
 
        if (session->kernel_session) {
-               ret = kernctl_session_metadata_regenerate(
+               ret = kernctl_session_regenerate_metadata(
                                session->kernel_session->fd);
                if (ret < 0) {
                        ERR("Failed to regenerate the kernel metadata");
@@ -3533,7 +3566,7 @@ int cmd_metadata_regenerate(struct ltt_session *session)
        }
 
        if (session->ust_session) {
-               ret = ust_metadata_regenerate(session->ust_session);
+               ret = ust_regenerate_metadata(session->ust_session);
                if (ret < 0) {
                        ERR("Failed to regenerate the UST metadata");
                        goto end;
@@ -3546,6 +3579,60 @@ end:
        return ret;
 }
 
+/*
+ * Command LTTNG_REGENERATE_STATEDUMP from the lttng-ctl library.
+ *
+ * Ask the tracer to regenerate a new statedump.
+ *
+ * Return 0 on success or else a LTTNG_ERR code.
+ */
+int cmd_regenerate_statedump(struct ltt_session *session)
+{
+       int ret;
+
+       assert(session);
+
+       if (!session->active) {
+               ret = LTTNG_ERR_SESSION_NOT_STARTED;
+               goto end;
+       }
+       ret = 0;
+
+       if (session->kernel_session) {
+               ret = kernctl_session_regenerate_statedump(
+                               session->kernel_session->fd);
+               /*
+                * Currently, the statedump in kernel can only fail if out
+                * of memory.
+                */
+               if (ret < 0) {
+                       if (ret == -ENOMEM) {
+                               ret = LTTNG_ERR_REGEN_STATEDUMP_NOMEM;
+                       } else {
+                               ret = LTTNG_ERR_REGEN_STATEDUMP_FAIL;
+                       }
+                       ERR("Failed to regenerate the kernel statedump");
+                       goto end;
+               }
+       }
+
+       if (session->ust_session) {
+               ret = ust_app_regenerate_statedump_all(session->ust_session);
+               /*
+                * Currently, the statedump in UST always returns 0.
+                */
+               if (ret < 0) {
+                       ret = LTTNG_ERR_REGEN_STATEDUMP_FAIL;
+                       ERR("Failed to regenerate the UST statedump");
+                       goto end;
+               }
+       }
+       DBG("Cmd regenerate statedump for session %s", session->name);
+       ret = LTTNG_OK;
+
+end:
+       return ret;
+}
 
 /*
  * Send relayd sockets from snapshot output to consumer. Ignore request if the
@@ -3578,10 +3665,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;
@@ -3813,7 +3902,7 @@ int cmd_snapshot_record(struct ltt_session *session,
         * set in no output mode.
         */
        if (session->output_traces) {
-               ret = LTTNG_ERR_EPERM;
+               ret = LTTNG_ERR_NOT_SNAPSHOT_SESSION;
                goto error;
        }
 
This page took 0.034337 seconds and 5 git commands to generate.