Fix: sessiond: lttng_channel object is not reclaimed
[lttng-tools.git] / src / bin / lttng-sessiond / ust-app.cpp
index f08e888c104627981c236cff801c414a9c199b02..62d323ee95619263864553464bb5bb4fa643def3 100644 (file)
@@ -287,6 +287,7 @@ void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx,
        int ret;
 
        LTTNG_ASSERT(ua_ctx);
+       ASSERT_RCU_READ_LOCKED();
 
        if (ua_ctx->obj) {
                pthread_mutex_lock(&app->sock_lock);
@@ -321,6 +322,7 @@ void delete_ust_app_event(int sock, struct ust_app_event *ua_event,
        int ret;
 
        LTTNG_ASSERT(ua_event);
+       ASSERT_RCU_READ_LOCKED();
 
        free(ua_event->filter);
        if (ua_event->exclusion != NULL)
@@ -443,25 +445,20 @@ void delete_ust_app_stream(int sock, struct ust_app_stream *stream,
                struct ust_app *app)
 {
        LTTNG_ASSERT(stream);
+       ASSERT_RCU_READ_LOCKED();
 
        (void) release_ust_app_stream(sock, stream, app);
        free(stream);
 }
 
-/*
- * We need to execute ht_destroy outside of RCU read-side critical
- * section and outside of call_rcu thread, so we postpone its execution
- * using ht_cleanup_push. It is simpler than to change the semantic of
- * the many callers of delete_ust_app_session().
- */
 static
 void delete_ust_app_channel_rcu(struct rcu_head *head)
 {
        struct ust_app_channel *ua_chan =
                caa_container_of(head, struct ust_app_channel, rcu_head);
 
-       ht_cleanup_push(ua_chan->ctx);
-       ht_cleanup_push(ua_chan->events);
+       lttng_ht_destroy(ua_chan->ctx);
+       lttng_ht_destroy(ua_chan->events);
        free(ua_chan);
 }
 
@@ -549,6 +546,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan,
        struct ust_registry_session *registry;
 
        LTTNG_ASSERT(ua_chan);
+       ASSERT_RCU_READ_LOCKED();
 
        DBG3("UST app deleting channel %s", ua_chan->name);
 
@@ -670,6 +668,7 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
 
        LTTNG_ASSERT(registry);
        LTTNG_ASSERT(socket);
+       ASSERT_RCU_READ_LOCKED();
 
        metadata_key = registry->metadata_key;
 
@@ -806,6 +805,7 @@ static int push_metadata(struct ust_registry_session *registry,
 
        LTTNG_ASSERT(registry);
        LTTNG_ASSERT(consumer);
+       ASSERT_RCU_READ_LOCKED();
 
        pthread_mutex_lock(&registry->lock);
        if (registry->metadata_closed) {
@@ -895,19 +895,13 @@ end:
        return ret;
 }
 
-/*
- * We need to execute ht_destroy outside of RCU read-side critical
- * section and outside of call_rcu thread, so we postpone its execution
- * using ht_cleanup_push. It is simpler than to change the semantic of
- * the many callers of delete_ust_app_session().
- */
 static
 void delete_ust_app_session_rcu(struct rcu_head *head)
 {
        struct ust_app_session *ua_sess =
                caa_container_of(head, struct ust_app_session, rcu_head);
 
-       ht_cleanup_push(ua_sess->channels);
+       lttng_ht_destroy(ua_sess->channels);
        free(ua_sess);
 }
 
@@ -927,6 +921,7 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
        struct ust_registry_session *registry;
 
        LTTNG_ASSERT(ua_sess);
+       ASSERT_RCU_READ_LOCKED();
 
        pthread_mutex_lock(&ua_sess->lock);
 
@@ -1004,8 +999,6 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
 /*
  * Delete a traceable application structure from the global list. Never call
  * this function outside of a call_rcu call.
- *
- * RCU read side lock should _NOT_ be held when calling this function.
  */
 static
 void delete_ust_app(struct ust_app *app)
@@ -1047,10 +1040,10 @@ void delete_ust_app(struct ust_app *app)
 
        rcu_read_unlock();
 
-       ht_cleanup_push(app->sessions);
-       ht_cleanup_push(app->ust_sessions_objd);
-       ht_cleanup_push(app->ust_objd);
-       ht_cleanup_push(app->token_to_event_notifier_rule_ht);
+       lttng_ht_destroy(app->sessions);
+       lttng_ht_destroy(app->ust_sessions_objd);
+       lttng_ht_destroy(app->ust_objd);
+       lttng_ht_destroy(app->token_to_event_notifier_rule_ht);
 
        /*
         * This could be NULL if the event notifier setup failed (e.g the app
@@ -1456,6 +1449,8 @@ struct ust_app *ust_app_find_by_sock(int sock)
        struct lttng_ht_node_ulong *node;
        struct lttng_ht_iter iter;
 
+       ASSERT_RCU_READ_LOCKED();
+
        lttng_ht_lookup(ust_app_ht_by_sock, (void *)((unsigned long) sock), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
        if (node == NULL) {
@@ -1478,6 +1473,8 @@ static struct ust_app *find_app_by_notify_sock(int sock)
        struct lttng_ht_node_ulong *node;
        struct lttng_ht_iter iter;
 
+       ASSERT_RCU_READ_LOCKED();
+
        lttng_ht_lookup(ust_app_ht_by_notify_sock, (void *)((unsigned long) sock),
                        &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
@@ -1546,6 +1543,7 @@ static struct ust_app_event_notifier_rule *find_ust_app_event_notifier_rule(
        struct ust_app_event_notifier_rule *event_notifier_rule = NULL;
 
        LTTNG_ASSERT(ht);
+       ASSERT_RCU_READ_LOCKED();
 
        lttng_ht_lookup(ht, &token, &iter);
        node = lttng_ht_iter_get_node_u64(&iter);
@@ -2823,6 +2821,7 @@ struct ust_app_ctx *find_ust_app_context(struct lttng_ht *ht,
 
        LTTNG_ASSERT(uctx);
        LTTNG_ASSERT(ht);
+       ASSERT_RCU_READ_LOCKED();
 
        /* Lookup using the lttng_ust_context_type and a custom match fct. */
        cds_lfht_lookup(ht->ht, ht->hash_fct((void *) uctx->ctx, lttng_ht_seed),
@@ -2851,6 +2850,8 @@ int create_ust_app_channel_context(struct ust_app_channel *ua_chan,
        int ret = 0;
        struct ust_app_ctx *ua_ctx;
 
+       ASSERT_RCU_READ_LOCKED();
+
        DBG2("UST app adding context to channel %s", ua_chan->name);
 
        ua_ctx = find_ust_app_context(ua_chan->ctx, uctx);
@@ -2952,6 +2953,8 @@ static int enable_ust_app_channel(struct ust_app_session *ua_sess,
        struct lttng_ht_node_str *ua_chan_node;
        struct ust_app_channel *ua_chan;
 
+       ASSERT_RCU_READ_LOCKED();
+
        lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
        ua_chan_node = lttng_ht_iter_get_node_str(&iter);
        if (ua_chan_node == NULL) {
@@ -3381,6 +3384,7 @@ static int create_channel_per_uid(struct ust_app *app,
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(ua_chan);
+       ASSERT_RCU_READ_LOCKED();
 
        DBG("UST app creating channel %s with per UID buffers", ua_chan->name);
 
@@ -3601,6 +3605,7 @@ static int ust_app_channel_send(struct ust_app *app,
        LTTNG_ASSERT(usess->active);
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(ua_chan);
+       ASSERT_RCU_READ_LOCKED();
 
        /* Handle buffer type before sending the channel to the application. */
        switch (usess->buffer_type) {
@@ -3659,6 +3664,8 @@ static int ust_app_channel_allocate(struct ust_app_session *ua_sess,
        struct lttng_ht_node_str *ua_chan_node;
        struct ust_app_channel *ua_chan;
 
+       ASSERT_RCU_READ_LOCKED();
+
        /* Lookup channel in the ust app session */
        lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
        ua_chan_node = lttng_ht_iter_get_node_str(&iter);
@@ -3706,6 +3713,8 @@ int create_ust_app_event(struct ust_app_session *ua_sess,
        int ret = 0;
        struct ust_app_event *ua_event;
 
+       ASSERT_RCU_READ_LOCKED();
+
        ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr);
        if (ua_event == NULL) {
                /* Only failure mode of alloc_ust_app_event(). */
@@ -3760,6 +3769,8 @@ int create_ust_app_event_notifier_rule(struct lttng_trigger *trigger,
        int ret = 0;
        struct ust_app_event_notifier_rule *ua_event_notifier_rule;
 
+       ASSERT_RCU_READ_LOCKED();
+
        ua_event_notifier_rule = alloc_ust_app_event_notifier_rule(trigger);
        if (ua_event_notifier_rule == NULL) {
                ret = -ENOMEM;
@@ -3817,6 +3828,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(app);
        LTTNG_ASSERT(consumer);
+       ASSERT_RCU_READ_LOCKED();
 
        registry = get_session_registry(ua_sess);
        /* The UST app session is held registry shall not be null. */
@@ -4618,8 +4630,6 @@ error:
 
 /*
  * Free and clean all traceable apps of the global list.
- *
- * Should _NOT_ be called with RCU read-side lock held.
  */
 void ust_app_clean_list(void)
 {
@@ -4666,13 +4676,13 @@ void ust_app_clean_list(void)
 
        /* Destroy is done only when the ht is empty */
        if (ust_app_ht) {
-               ht_cleanup_push(ust_app_ht);
+               lttng_ht_destroy(ust_app_ht);
        }
        if (ust_app_ht_by_sock) {
-               ht_cleanup_push(ust_app_ht_by_sock);
+               lttng_ht_destroy(ust_app_ht_by_sock);
        }
        if (ust_app_ht_by_notify_sock) {
-               ht_cleanup_push(ust_app_ht_by_notify_sock);
+               lttng_ht_destroy(ust_app_ht_by_notify_sock);
        }
 }
 
@@ -5806,6 +5816,8 @@ void ust_app_synchronize_event_notifier_rules(struct ust_app *app)
        struct ust_app_event_notifier_rule *event_notifier_rule;
        unsigned int count, i;
 
+       ASSERT_RCU_READ_LOCKED();
+
        if (!ust_app_supports_notifiers(app)) {
                goto end;
        }
@@ -5957,6 +5969,7 @@ void ust_app_synchronize_all_channels(struct ltt_ust_session *usess,
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(app);
+       ASSERT_RCU_READ_LOCKED();
 
        cds_lfht_for_each_entry(usess->domain_global.channels->ht, &uchan_iter,
                        uchan, node.node) {
@@ -6086,6 +6099,7 @@ void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app)
 {
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(usess->active);
+       ASSERT_RCU_READ_LOCKED();
 
        DBG2("UST app global update for app sock %d for session id %" PRIu64,
                        app->sock, usess->id);
@@ -6120,6 +6134,8 @@ void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app)
  */
 void ust_app_global_update_event_notifier_rules(struct ust_app *app)
 {
+       ASSERT_RCU_READ_LOCKED();
+
        DBG2("UST application global event notifier rules update: app = '%s', pid = %d",
                        app->name, app->pid);
 
@@ -6282,6 +6298,7 @@ static struct ust_app_session *find_session_by_objd(struct ust_app *app,
        struct ust_app_session *ua_sess = NULL;
 
        LTTNG_ASSERT(app);
+       ASSERT_RCU_READ_LOCKED();
 
        lttng_ht_lookup(app->ust_sessions_objd, (void *)((unsigned long) objd), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
@@ -6309,6 +6326,7 @@ static struct ust_app_channel *find_channel_by_objd(struct ust_app *app,
        struct ust_app_channel *ua_chan = NULL;
 
        LTTNG_ASSERT(app);
+       ASSERT_RCU_READ_LOCKED();
 
        lttng_ht_lookup(app->ust_objd, (void *)((unsigned long) objd), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
@@ -6323,6 +6341,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 +6453,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;
@@ -6389,6 +6505,13 @@ static int reply_ust_register_channel(int sock, int cobjd,
        /* 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
This page took 0.028671 seconds and 4 git commands to generate.