Custom upgrade: refactor: ust_app_find_by_pid -> ust_app_with_pid_exists
[deliverable/lttng-tools.git] / src / bin / lttng-sessiond / ust-app.c
index 3040d0a3bdf70d700bd59c46039da6cdbe3c43de..e180bff2abe45db514504c2c22a5a7b34a15d2a9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 EfficiOS Inc.
  * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
  * SPDX-License-Identifier: GPL-2.0-only
@@ -49,7 +49,7 @@
 #include "rotate.h"
 #include "event.h"
 #include "event-notifier-error-accounting.h"
-
+#include "ust-field-utils.h"
 
 struct lttng_ht *ust_app_ht;
 struct lttng_ht *ust_app_ht_by_sock;
@@ -1342,7 +1342,7 @@ static struct ust_app_event_notifier_rule *alloc_ust_app_event_notifier_rule(
        case LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE:
                break;
        default:
-               /* Error occured. */
+               /* Error occurred. */
                ERR("Failed to generate exclusions from trigger while allocating an event notifier rule");
                goto error_put_trigger;
        }
@@ -2151,7 +2151,7 @@ static int init_ust_event_notifier_from_event_rule(
 
        event_notifier->event.instrumentation = LTTNG_UST_ABI_TRACEPOINT;
        ret = lttng_strncpy(event_notifier->event.name, pattern,
-                       LTTNG_UST_ABI_SYM_NAME_LEN - 1);
+                       sizeof(event_notifier->event.name));
        if (ret) {
                ERR("Failed to copy event rule pattern to notifier: pattern = '%s' ",
                                pattern);
@@ -2415,8 +2415,8 @@ static void shadow_copy_session(struct ust_app_session *ua_sess,
        switch (ua_sess->buffer_type) {
        case LTTNG_BUFFER_PER_PID:
                ret = snprintf(ua_sess->path, sizeof(ua_sess->path),
-                               DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s", app->name, app->pid,
-                               datetime);
+                               DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s-%ld", app->name, app->pid,
+                               datetime, ua_sess->id);
                break;
        case LTTNG_BUFFER_PER_UID:
                ret = snprintf(ua_sess->path, sizeof(ua_sess->path),
@@ -2444,8 +2444,8 @@ static void shadow_copy_session(struct ust_app_session *ua_sess,
                switch (ua_sess->buffer_type) {
                case LTTNG_BUFFER_PER_PID:
                        ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path),
-                                       "/" DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s",
-                                       app->name, app->pid, datetime);
+                                       "/" DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s-%ld",
+                                       app->name, app->pid, datetime, ua_sess->id);
                        break;
                case LTTNG_BUFFER_PER_UID:
                        ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path),
@@ -3317,7 +3317,7 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan,
        /* Send all streams to application. */
        pthread_mutex_lock(&buf_reg_chan->stream_list_lock);
        cds_list_for_each_entry(reg_stream, &buf_reg_chan->streams, lnode) {
-               struct ust_app_stream stream;
+               struct ust_app_stream stream = {};
 
                ret = duplicate_stream_object(reg_stream, &stream);
                if (ret < 0) {
@@ -3334,8 +3334,8 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan,
                                 * Treat this the same way as an application
                                 * that is exiting.
                                 */
-                               WARN("Communication with application %d timed out on send_stream for stream \"%s\" of channel \"%s\" of session \"%" PRIu64 "\".",
-                                               app->pid, stream.name,
+                               WARN("Communication with application %d timed out on send_stream for stream of channel \"%s\" of session \"%" PRIu64 "\".",
+                                               app->pid,
                                                ua_chan->name,
                                                ua_sess->tracing_id);
                                ret = -ENOTCONN;
@@ -3910,28 +3910,25 @@ error:
 }
 
 /*
- * Return ust app pointer or NULL if not found. RCU read side lock MUST be
+ * Check if a ust_app with a given pid is present. RCU read side lock MUST be
  * acquired before calling this function.
  */
-struct ust_app *ust_app_find_by_pid(pid_t pid)
+bool ust_app_with_pid_exists(pid_t pid)
 {
-       struct ust_app *app = NULL;
        struct lttng_ht_node_ulong *node;
        struct lttng_ht_iter iter;
+       bool present = false;
 
        lttng_ht_lookup(ust_app_ht, (void *)((unsigned long) pid), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
        if (node == NULL) {
-               DBG2("UST app no found with pid %d", pid);
-               goto error;
+               DBG2("UST app not found with pid %d", pid);
+               goto end;
        }
 
-       DBG2("Found UST app by pid %d", pid);
-
-       app = caa_container_of(node, struct ust_app, pid_n);
-
-error:
-       return app;
+       present = true;
+end:
+       return present;
 }
 
 /*
@@ -4051,10 +4048,13 @@ void ust_app_add(struct ust_app *app)
        rcu_read_lock();
 
        /*
-        * On a re-registration, we want to kick out the previous registration of
-        * that pid
+        * Accept duplicate pid to accommodate the possibility of multiple
+        * lttng-ust per process. Both lttng-ust instance will register
+        * themselves and be unique in term of socket.
+        * All operations on pid should expects that multiple "app" be present
+        * with the same pid.
         */
-       lttng_ht_add_replace_ulong(ust_app_ht, &app->pid_n);
+       lttng_ht_add_ulong(ust_app_ht, &app->pid_n);
 
        /*
         * The socket _should_ be unique until _we_ call close. So, a add_unique
@@ -4328,17 +4328,9 @@ void ust_app_unregister(int sock)
        iter.iter.node = &lta->notify_sock_n.node;
        (void) lttng_ht_del(ust_app_ht_by_notify_sock, &iter);
 
-       /*
-        * Ignore return value since the node might have been removed before by an
-        * add replace during app registration because the PID can be reassigned by
-        * the OS.
-        */
        iter.iter.node = &lta->pid_n.node;
        ret = lttng_ht_del(ust_app_ht, &iter);
-       if (ret) {
-               DBG3("Unregister app by PID %d failed. This can happen on pid reuse",
-                               lta->pid);
-       }
+       assert(!ret);
 
        /* Free memory */
        call_rcu(&lta->pid_n.head, delete_ust_app_rcu);
@@ -6323,6 +6315,104 @@ error:
        return ua_chan;
 }
 
+/*
+ * Fixup legacy context fields for comparison:
+ * - legacy array becomes array_nestable,
+ * - legacy struct becomes struct_nestable,
+ * - legacy variant becomes variant_nestable,
+ * legacy sequences are not emitted in LTTng-UST contexts.
+ */
+static int ust_app_fixup_legacy_context_fields(size_t *_nr_fields,
+               struct lttng_ust_ctl_field **_fields)
+{
+       struct lttng_ust_ctl_field *fields = *_fields, *new_fields = NULL;
+       size_t nr_fields = *_nr_fields, new_nr_fields = 0, i, j;
+       bool found = false;
+       int ret = 0;
+
+       for (i = 0; i < nr_fields; i++) {
+               const struct lttng_ust_ctl_field *field = &fields[i];
+
+               switch (field->type.atype) {
+               case lttng_ust_ctl_atype_sequence:
+                       ERR("Unexpected legacy sequence context.");
+                       ret = -EINVAL;
+                       goto end;
+               case lttng_ust_ctl_atype_array:
+                       switch (field->type.u.legacy.array.elem_type.atype) {
+                       case lttng_ust_ctl_atype_integer:
+                               break;
+                       default:
+                               ERR("Unexpected legacy array element type in context.");
+                               ret = -EINVAL;
+                               goto end;
+                       }
+                       found = true;
+                       /* One field for array_nested, one field for elem type. */
+                       new_nr_fields += 2;
+                       break;
+
+               case lttng_ust_ctl_atype_struct:        /* Fallthrough */
+               case lttng_ust_ctl_atype_variant:
+                       found = true;
+                       new_nr_fields++;
+                       break;
+               default:
+                       new_nr_fields++;
+                       break;
+               }
+       }
+       if (!found) {
+               goto end;
+       }
+       new_fields = (struct lttng_ust_ctl_field *) zmalloc(sizeof(*new_fields) * new_nr_fields);
+       if (!new_fields) {
+               ret = -ENOMEM;
+               goto end;
+       }
+       for (i = 0, j = 0; i < nr_fields; i++, j++) {
+               const struct lttng_ust_ctl_field *field = &fields[i];
+               struct lttng_ust_ctl_field *new_field = &new_fields[j];
+
+               switch (field->type.atype) {
+               case lttng_ust_ctl_atype_array:
+                       /* One field for array_nested, one field for elem type. */
+                       strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1);
+                       new_field->type.atype = lttng_ust_ctl_atype_array_nestable;
+                       new_field->type.u.array_nestable.length = field->type.u.legacy.array.length;
+                       new_field->type.u.array_nestable.alignment = 0;
+                       new_field = &new_fields[++j];   /* elem type */
+                       new_field->type.atype = field->type.u.legacy.array.elem_type.atype;
+                       assert(new_field->type.atype == lttng_ust_ctl_atype_integer);
+                       new_field->type.u.integer = field->type.u.legacy.array.elem_type.u.basic.integer;
+                       break;
+               case lttng_ust_ctl_atype_struct:
+                       strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1);
+                       new_field->type.atype = lttng_ust_ctl_atype_struct_nestable;
+                       new_field->type.u.struct_nestable.nr_fields = field->type.u.legacy._struct.nr_fields;
+                       new_field->type.u.struct_nestable.alignment = 0;
+                       break;
+               case lttng_ust_ctl_atype_variant:
+                       strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1);
+                       new_field->type.atype = lttng_ust_ctl_atype_variant_nestable;
+                       new_field->type.u.variant_nestable.nr_choices = field->type.u.legacy.variant.nr_choices;
+                       strncpy(new_field->type.u.variant_nestable.tag_name,
+                               field->type.u.legacy.variant.tag_name,
+                               LTTNG_UST_ABI_SYM_NAME_LEN - 1);
+                       new_field->type.u.variant_nestable.alignment = 0;
+                       break;
+               default:
+                       *new_field = *field;
+                       break;
+               }
+       }
+       free(fields);
+       *_fields = new_fields;
+       *_nr_fields = new_nr_fields;
+end:
+       return ret;
+}
+
 /*
  * Reply to a register channel notification from an application on the notify
  * socket. The channel metadata is also created.
@@ -6337,7 +6427,7 @@ static int reply_ust_register_channel(int sock, int cobjd,
        int ret, ret_code = 0;
        uint32_t chan_id;
        uint64_t chan_reg_key;
-       enum lttng_ust_ctl_channel_header type;
+       enum lttng_ust_ctl_channel_header type = LTTNG_UST_CTL_CHANNEL_HEADER_UNKNOWN;
        struct ust_app *app;
        struct ust_app_channel *ua_chan;
        struct ust_app_session *ua_sess;
@@ -6351,7 +6441,7 @@ static int reply_ust_register_channel(int sock, int cobjd,
        if (!app) {
                DBG("Application socket %d is being torn down. Abort event notify",
                                sock);
-               ret = 0;
+               ret = -1;
                goto error_rcu_unlock;
        }
 
@@ -6386,6 +6476,16 @@ static int reply_ust_register_channel(int sock, int cobjd,
        ust_reg_chan = ust_registry_channel_find(registry, chan_reg_key);
        assert(ust_reg_chan);
 
+       /* Channel id is set during the object creation. */
+       chan_id = ust_reg_chan->chan_id;
+
+       ret = ust_app_fixup_legacy_context_fields(&nr_fields, &fields);
+       if (ret < 0) {
+               ERR("Registering application channel due to legacy context fields fixup error: pid = %d, sock = %d",
+                       app->pid, app->sock);
+               ret_code = -EINVAL;
+               goto reply;
+       }
        if (!ust_reg_chan->register_done) {
                /*
                 * TODO: eventually use the registry event count for
@@ -6400,9 +6500,19 @@ static int reply_ust_register_channel(int sock, int cobjd,
        } else {
                /* Get current already assigned values. */
                type = ust_reg_chan->header_type;
+               /*
+                * Validate that the context fields match between
+                * registry and newcoming application.
+                */
+               if (!match_lttng_ust_ctl_field_array(ust_reg_chan->ctx_fields,
+                               ust_reg_chan->nr_ctx_fields,
+                               fields, nr_fields)) {
+                       ERR("Registering application channel due to context field mismatch: pid = %d, sock = %d",
+                               app->pid, app->sock);
+                       ret_code = -EINVAL;
+                       goto reply;
+               }
        }
-       /* Channel id is set during the object creation. */
-       chan_id = ust_reg_chan->chan_id;
 
        /* Append to metadata */
        if (!ust_reg_chan->metadata_dumped) {
@@ -6472,7 +6582,7 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
        if (!app) {
                DBG("Application socket %d is being torn down. Abort event notify",
                                sock);
-               ret = 0;
+               ret = -1;
                goto error_rcu_unlock;
        }
 
@@ -6578,6 +6688,7 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name,
                DBG("Application socket %d is being torn down. Aborting enum registration",
                                sock);
                free(entries);
+               ret = -1;
                goto error_rcu_unlock;
        }
 
This page took 0.034175 seconds and 5 git commands to generate.