Missing error handling: ust_app_ht_alloc should return error status
[lttng-tools.git] / src / bin / lttng-sessiond / ust-app.c
index 7f27eae078a45abd28535db63760e3aaecc1cf64..9ab5f77e0067b8f129b8ce4e17c2bba12d386f43 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <errno.h>
 #include <inttypes.h>
 #include <pthread.h>
@@ -1446,11 +1447,15 @@ int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess,
        }
 
        /* If event not enabled, disable it on the tracer */
-       if (ua_event->enabled == 0) {
-               ret = disable_ust_event(app, ua_sess, ua_event);
+       if (ua_event->enabled) {
+               /*
+                * We now need to explicitly enable the event, since it
+                * is now disabled at creation.
+                */
+               ret = enable_ust_event(app, ua_sess, ua_event);
                if (ret < 0) {
                        /*
-                        * If we hit an EPERM, something is wrong with our disable call. If
+                        * If we hit an EPERM, something is wrong with our enable call. If
                         * we get an EEXIST, there is a problem on the tracer side since we
                         * just created it.
                         */
@@ -1552,7 +1557,7 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan,
                }
                lttng_ht_node_init_ulong(&ua_ctx->node,
                                (unsigned long) ua_ctx->ctx.ctx);
-               lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node);
+               lttng_ht_add_ulong(ua_chan->ctx, &ua_ctx->node);
                cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list);
        }
 
@@ -1727,7 +1732,6 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess,
                if (ret < 0) {
                        goto error;
                }
-               buffer_reg_pid_add(reg_pid);
        } else {
                goto end;
        }
@@ -1740,9 +1744,18 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess,
                        app->byte_order, app->version.major,
                        app->version.minor);
        if (ret < 0) {
+               /*
+                * reg_pid->registry->reg.ust is NULL upon error, so we need to
+                * destroy the buffer registry, because it is always expected
+                * that if the buffer registry can be found, its ust registry is
+                * non-NULL.
+                */
+               buffer_reg_pid_destroy(reg_pid);
                goto error;
        }
 
+       buffer_reg_pid_add(reg_pid);
+
        DBG3("UST app buffer registry per PID created successfully");
 
 end:
@@ -1783,7 +1796,6 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess,
                if (ret < 0) {
                        goto error;
                }
-               buffer_reg_uid_add(reg_uid);
        } else {
                goto end;
        }
@@ -1796,13 +1808,21 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess,
                        app->byte_order, app->version.major,
                        app->version.minor);
        if (ret < 0) {
+               /*
+                * reg_uid->registry->reg.ust is NULL upon error, so we need to
+                * destroy the buffer registry, because it is always expected
+                * that if the buffer registry can be found, its ust registry is
+                * non-NULL.
+                */
+               buffer_reg_uid_destroy(reg_uid, NULL);
                goto error;
        }
        /* Add node to teardown list of the session. */
        cds_list_add(&reg_uid->lnode, &usess->buffer_reg_uid_list);
 
-       DBG3("UST app buffer registry per UID created successfully");
+       buffer_reg_uid_add(reg_uid);
 
+       DBG3("UST app buffer registry per UID created successfully");
 end:
        if (regp) {
                *regp = reg_uid;
@@ -1855,6 +1875,7 @@ static int create_ust_app_session(struct ltt_ust_session *usess,
                /* Init local registry. */
                ret = setup_buffer_reg_pid(ua_sess, app, NULL);
                if (ret < 0) {
+                       delete_ust_app_session(-1, ua_sess, app);
                        goto error;
                }
                break;
@@ -1862,6 +1883,7 @@ static int create_ust_app_session(struct ltt_ust_session *usess,
                /* Look for a global registry. If none exists, create one. */
                ret = setup_buffer_reg_uid(usess, app, NULL);
                if (ret < 0) {
+                       delete_ust_app_session(-1, ua_sess, app);
                        goto error;
                }
                break;
@@ -1923,6 +1945,75 @@ error:
        return ret;
 }
 
+/*
+ * Match function for a hash table lookup of ust_app_ctx.
+ *
+ * It matches an ust app context based on the context type and, in the case
+ * of perf counters, their name.
+ */
+static int ht_match_ust_app_ctx(struct cds_lfht_node *node, const void *_key)
+{
+       struct ust_app_ctx *ctx;
+       const struct lttng_ust_context *key;
+
+       assert(node);
+       assert(_key);
+
+       ctx = caa_container_of(node, struct ust_app_ctx, node.node);
+       key = _key;
+
+       /* Context type */
+       if (ctx->ctx.ctx != key->ctx) {
+               goto no_match;
+       }
+
+       /* Check the name in the case of perf thread counters. */
+       if (key->ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) {
+               if (strncmp(key->u.perf_counter.name,
+                       ctx->ctx.u.perf_counter.name,
+                       sizeof(key->u.perf_counter.name))) {
+                       goto no_match;
+               }
+       }
+
+       /* Match. */
+       return 1;
+
+no_match:
+       return 0;
+}
+
+/*
+ * Lookup for an ust app context from an lttng_ust_context.
+ *
+ * Must be called while holding RCU read side lock.
+ * Return an ust_app_ctx object or NULL on error.
+ */
+static
+struct ust_app_ctx *find_ust_app_context(struct lttng_ht *ht,
+               struct lttng_ust_context *uctx)
+{
+       struct lttng_ht_iter iter;
+       struct lttng_ht_node_ulong *node;
+       struct ust_app_ctx *app_ctx = NULL;
+
+       assert(uctx);
+       assert(ht);
+
+       /* 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),
+                       ht_match_ust_app_ctx, uctx, &iter.iter);
+       node = lttng_ht_iter_get_node_ulong(&iter);
+       if (!node) {
+               goto end;
+       }
+
+       app_ctx = caa_container_of(node, struct ust_app_ctx, node);
+
+end:
+       return app_ctx;
+}
+
 /*
  * Create a context for the channel on the tracer.
  *
@@ -1934,15 +2025,12 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess,
                struct ust_app *app)
 {
        int ret = 0;
-       struct lttng_ht_iter iter;
-       struct lttng_ht_node_ulong *node;
        struct ust_app_ctx *ua_ctx;
 
        DBG2("UST app adding context to channel %s", ua_chan->name);
 
-       lttng_ht_lookup(ua_chan->ctx, (void *)((unsigned long)uctx->ctx), &iter);
-       node = lttng_ht_iter_get_node_ulong(&iter);
-       if (node != NULL) {
+       ua_ctx = find_ust_app_context(ua_chan->ctx, uctx);
+       if (ua_ctx) {
                ret = -EEXIST;
                goto error;
        }
@@ -1955,7 +2043,7 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess,
        }
 
        lttng_ht_node_init_ulong(&ua_ctx->node, (unsigned long) ua_ctx->ctx.ctx);
-       lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node);
+       lttng_ht_add_ulong(ua_chan->ctx, &ua_ctx->node);
        cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list);
 
        ret = create_ust_channel_context(ua_chan, ua_ctx, app);
@@ -2450,6 +2538,8 @@ static int create_channel_per_uid(struct ust_app *app,
                /* Create the buffer registry channel object. */
                ret = create_buffer_reg_channel(reg_uid->registry, ua_chan, &reg_chan);
                if (ret < 0) {
+                       ERR("Error creating the UST channel \"%s\" registry instance",
+                               ua_chan->name);
                        goto error;
                }
                assert(reg_chan);
@@ -2461,6 +2551,9 @@ static int create_channel_per_uid(struct ust_app *app,
                ret = do_consumer_create_channel(usess, ua_sess, ua_chan,
                                app->bits_per_long, reg_uid->registry->reg.ust);
                if (ret < 0) {
+                       ERR("Error creating UST channel \"%s\" on the consumer daemon",
+                               ua_chan->name);
+
                        /*
                         * Let's remove the previously created buffer registry channel so
                         * it's not visible anymore in the session registry.
@@ -2477,6 +2570,8 @@ static int create_channel_per_uid(struct ust_app *app,
                 */
                ret = setup_buffer_reg_channel(reg_uid->registry, ua_chan, reg_chan);
                if (ret < 0) {
+                       ERR("Error setting up UST channel \"%s\"",
+                               ua_chan->name);
                        goto error;
                }
 
@@ -2485,6 +2580,10 @@ static int create_channel_per_uid(struct ust_app *app,
        /* Send buffers to the application. */
        ret = send_channel_uid_to_ust(reg_chan, app, ua_sess, ua_chan);
        if (ret < 0) {
+               /*
+                * Don't report error to the console, since it may be
+                * caused by application concurrently exiting.
+                */
                goto error;
        }
 
@@ -2519,6 +2618,8 @@ static int create_channel_per_pid(struct ust_app *app,
        /* Create and add a new channel registry to session. */
        ret = ust_registry_channel_add(registry, ua_chan->key);
        if (ret < 0) {
+               ERR("Error creating the UST channel \"%s\" registry instance",
+                       ua_chan->name);
                goto error;
        }
 
@@ -2526,11 +2627,17 @@ static int create_channel_per_pid(struct ust_app *app,
        ret = do_consumer_create_channel(usess, ua_sess, ua_chan,
                        app->bits_per_long, registry);
        if (ret < 0) {
+               ERR("Error creating UST channel \"%s\" on the consumer daemon",
+                       ua_chan->name);
                goto error;
        }
 
        ret = send_channel_pid_to_ust(app, ua_sess, ua_chan);
        if (ret < 0) {
+               /*
+                * Don't report error to the console, since it may be
+                * caused by application concurrently exiting.
+                */
                goto error;
        }
 
@@ -2953,9 +3060,9 @@ int ust_app_version(struct ust_app *app)
        ret = ustctl_tracer_version(app->sock, &app->version);
        if (ret < 0) {
                if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
-                       ERR("UST app %d verson failed with ret %d", app->sock, ret);
+                       ERR("UST app %d version failed with ret %d", app->sock, ret);
                } else {
-                       DBG3("UST app %d verion failed. Application is dead", app->sock);
+                       DBG3("UST app %d version failed. Application is dead", app->sock);
                }
        }
 
@@ -3331,11 +3438,21 @@ void ust_app_clean_list(void)
 /*
  * Init UST app hash table.
  */
-void ust_app_ht_alloc(void)
+int ust_app_ht_alloc(void)
 {
        ust_app_ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
+       if (!ust_app_ht) {
+               return -1;
+       }
        ust_app_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
+       if (!ust_app_ht_by_sock) {
+               return -1;
+       }
        ust_app_ht_by_notify_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
+       if (!ust_app_ht_by_notify_sock) {
+               return -1;
+       }
+       return 0;
 }
 
 /*
@@ -4911,28 +5028,19 @@ void ust_app_destroy(struct ust_app *app)
  * Return 0 on success or else a negative value.
  */
 int ust_app_snapshot_record(struct ltt_ust_session *usess,
-               struct snapshot_output *output, int wait, unsigned int nb_streams)
+               struct snapshot_output *output, int wait, uint64_t max_stream_size)
 {
        int ret = 0;
        unsigned int snapshot_done = 0;
        struct lttng_ht_iter iter;
        struct ust_app *app;
        char pathname[PATH_MAX];
-       uint64_t max_stream_size = 0;
 
        assert(usess);
        assert(output);
 
        rcu_read_lock();
 
-       /*
-        * Compute the maximum size of a single stream if a max size is asked by
-        * the caller.
-        */
-       if (output->max_size > 0 && nb_streams > 0) {
-               max_stream_size = output->max_size / nb_streams;
-       }
-
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_UID:
        {
@@ -4962,30 +5070,16 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
                        /* Add the UST default trace dir to path. */
                        cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
                                        reg_chan, node.node) {
-
-                               /*
-                                * Make sure the maximum stream size is not lower than the
-                                * subbuffer size or else it's an error since we won't be able to
-                                * snapshot anything.
-                                */
-                               if (max_stream_size &&
-                                               reg_chan->subbuf_size > max_stream_size) {
-                                       ret = -EINVAL;
-                                       DBG3("UST app snapshot record maximum stream size %" PRIu64
-                                                       " is smaller than subbuffer size of %zu",
-                                                       max_stream_size, reg_chan->subbuf_size);
-                                       goto error;
-                               }
-                               ret = consumer_snapshot_channel(socket, reg_chan->consumer_key, output, 0,
-                                               usess->uid, usess->gid, pathname, wait,
+                               ret = consumer_snapshot_channel(socket, reg_chan->consumer_key,
+                                               output, 0, usess->uid, usess->gid, pathname, wait,
                                                max_stream_size);
                                if (ret < 0) {
                                        goto error;
                                }
                        }
-                       ret = consumer_snapshot_channel(socket, reg->registry->reg.ust->metadata_key, output,
-                                       1, usess->uid, usess->gid, pathname, wait,
-                                       max_stream_size);
+                       ret = consumer_snapshot_channel(socket,
+                                       reg->registry->reg.ust->metadata_key, output, 1,
+                                       usess->uid, usess->gid, pathname, wait, max_stream_size);
                        if (ret < 0) {
                                goto error;
                        }
@@ -5027,22 +5121,8 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess,
 
                        cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
                                        ua_chan, node.node) {
-                               /*
-                                * Make sure the maximum stream size is not lower than the
-                                * subbuffer size or else it's an error since we won't be able to
-                                * snapshot anything.
-                                */
-                               if (max_stream_size &&
-                                               ua_chan->attr.subbuf_size > max_stream_size) {
-                                       ret = -EINVAL;
-                                       DBG3("UST app snapshot record maximum stream size %" PRIu64
-                                                       " is smaller than subbuffer size of %" PRIu64,
-                                                       max_stream_size, ua_chan->attr.subbuf_size);
-                                       goto error;
-                               }
-
-                               ret = consumer_snapshot_channel(socket, ua_chan->key, output, 0,
-                                               ua_sess->euid, ua_sess->egid, pathname, wait,
+                               ret = consumer_snapshot_channel(socket, ua_chan->key, output,
+                                               0, ua_sess->euid, ua_sess->egid, pathname, wait,
                                                max_stream_size);
                                if (ret < 0) {
                                        goto error;
@@ -5099,10 +5179,12 @@ unsigned int ust_app_get_nb_stream(struct ltt_ust_session *usess)
                cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
                        struct buffer_reg_channel *reg_chan;
 
+                       rcu_read_lock();
                        cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
                                        reg_chan, node.node) {
                                ret += reg_chan->stream_count;
                        }
+                       rcu_read_unlock();
                }
                break;
        }
This page took 0.029364 seconds and 4 git commands to generate.