Add important DEBUG statement
[lttng-tools.git] / lttng-sessiond / ust-app.c
index d93dc90f579437d992ddb783edcafef57cffeec3..8520efb440e71cb84499609c1beb83bcccca8e36 100644 (file)
 
 #include "hashtable.h"
 #include "ust-app.h"
-#include "../hashtable/hash.h"
-#include "ust-ctl.h"
 #include "ust-consumer.h"
+#include "ust-ctl.h"
+
+/*
+ * Delete ust app event safely. RCU read lock must be held before calling
+ * this function.
+ */
+static void delete_ust_app_event(int sock, struct ust_app_event *ua_event)
+{
+       /* TODO : remove context */
+       //struct ust_app_ctx *ltctx;
+       //cds_lfht_for_each_entry(lte->ctx, &iter, ltctx, node) {
+       //      delete_ust_app_ctx(sock, ltctx);
+       //}
+
+       ustctl_release_object(sock, ua_event->obj);
+       free(ua_event);
+}
+
+/*
+ * Delete ust app stream safely. RCU read lock must be held before calling
+ * this function.
+ */
+static void delete_ust_app_stream(int sock, struct ltt_ust_stream *stream)
+{
+       //TODO
+       //stream is used for passing to consumer.
+       //send_channel_streams is responsible for freeing the streams.
+       //note that this will not play well with flight recorder mode:
+       //we might need a criterion to discard the streams.
+}
+
+/*
+ * Delete ust app channel safely. RCU read lock must be held before calling
+ * this function.
+ */
+static void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan)
+{
+       int ret;
+       struct cds_lfht_iter iter;
+       struct ust_app_event *ua_event;
+       struct ltt_ust_stream *stream, *stmp;
+
+       cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) {
+               delete_ust_app_stream(sock, stream);
+       }
+
+       /* TODO : remove channel context */
+       //cds_lfht_for_each_entry(ltc->ctx, &iter, ltctx, node) {
+       //      hashtable_del(ltc->ctx, &iter);
+       //      delete_ust_app_ctx(sock, ltctx);
+       //}
+       //ret = hashtable_destroy(ltc->ctx);
+
+       cds_lfht_for_each_entry(ua_chan->events, &iter, ua_event, node) {
+               hashtable_del(ua_chan->events, &iter);
+               delete_ust_app_event(sock, ua_event);
+       }
+
+       ret = hashtable_destroy(ua_chan->events);
+       if (ret < 0) {
+               ERR("UST app destroy session hashtable failed");
+               goto error;
+       }
+
+error:
+       return;
+}
+
+/*
+ * Delete ust app session safely. RCU read lock must be held before calling
+ * this function.
+ */
+static void delete_ust_app_session(int sock,
+               struct ust_app_session *ua_sess)
+{
+       int ret;
+       struct cds_lfht_iter iter;
+       struct ust_app_channel *ua_chan;
+
+       if (ua_sess->metadata) {
+               /*
+                * We do NOT release the stream object and metadata object since they
+                * are release when fds are sent to the consumer.
+                */
+       }
+
+       cds_lfht_for_each_entry(ua_sess->channels, &iter, ua_chan, node) {
+               hashtable_del(ua_sess->channels, &iter);
+               delete_ust_app_channel(sock, ua_chan);
+       }
+
+       ret = hashtable_destroy(ua_sess->channels);
+       if (ret < 0) {
+               ERR("UST app destroy session hashtable failed");
+               goto error;
+       }
+
+error:
+       return;
+}
 
 /*
  * Delete a traceable application structure from the global list.
@@ -43,18 +141,16 @@ static void delete_ust_app(struct ust_app *lta)
        int ret;
        struct cds_lfht_node *node;
        struct cds_lfht_iter iter;
+       struct ust_app_session *lts;
 
        rcu_read_lock();
 
-       /* TODO: clean session hashtable */
-       free(lta->sessions);
-       close(lta->key.sock);
-
        /* Remove from apps hash table */
        node = hashtable_lookup(ust_app_ht,
                        (void *) ((unsigned long) lta->key.pid), sizeof(void *), &iter);
        if (node == NULL) {
                ERR("UST app pid %d not found in hash table", lta->key.pid);
+               goto end;
        } else {
                ret = hashtable_del(ust_app_ht, &iter);
                if (ret) {
@@ -70,6 +166,7 @@ static void delete_ust_app(struct ust_app *lta)
                        (void *) ((unsigned long) lta->key.sock), sizeof(void *), &iter);
        if (node == NULL) {
                ERR("UST app key %d not found in key hash table", lta->key.sock);
+               goto end;
        } else {
                ret = hashtable_del(ust_app_sock_key_map, &iter);
                if (ret) {
@@ -81,8 +178,30 @@ static void delete_ust_app(struct ust_app *lta)
                }
        }
 
-       free(lta);
+       /* Socket is already closed at this point */
 
+       /* Delete ust app sessions info */
+       if (lta->sock_closed) {
+               lta->key.sock = -1;
+       }
+
+       cds_lfht_for_each_entry(lta->sessions, &iter, lts, node) {
+               hashtable_del(lta->sessions, &iter);
+               delete_ust_app_session(lta->key.sock, lts);
+       }
+
+       ret = hashtable_destroy(lta->sessions);
+       if (ret < 0) {
+               ERR("UST app destroy session hashtable failed");
+               goto end;
+       }
+
+       if (lta->key.sock >= 0) {
+               close(lta->key.sock);
+       }
+
+       free(lta);
+end:
        rcu_read_unlock();
 }
 
@@ -113,7 +232,6 @@ static struct ust_app *find_app_by_sock(int sock)
                        (void *)((unsigned long) sock), sizeof(void *), &iter);
        if (node == NULL) {
                DBG2("UST app find by sock %d key not found", sock);
-               rcu_read_unlock();
                goto error;
        }
 
@@ -123,10 +241,8 @@ static struct ust_app *find_app_by_sock(int sock)
                        (void *)((unsigned long) key->pid), sizeof(void *), &iter);
        if (node == NULL) {
                DBG2("UST app find by sock %d not found", sock);
-               rcu_read_unlock();
                goto error;
        }
-
        return caa_container_of(node, struct ust_app, node);
 
 error:
@@ -153,7 +269,6 @@ struct ust_app *ust_app_find_by_pid(pid_t pid)
        node = hashtable_lookup(ust_app_ht,
                        (void *)((unsigned long) pid), sizeof(void *), &iter);
        if (node == NULL) {
-               rcu_read_unlock();
                DBG2("UST app no found with pid %d", pid);
                goto error;
        }
@@ -164,6 +279,7 @@ struct ust_app *ust_app_find_by_pid(pid_t pid)
        return caa_container_of(node, struct ust_app, node);
 
 error:
+       rcu_read_unlock();
        return NULL;
 }
 
@@ -177,7 +293,7 @@ int ust_app_register(struct ust_register_msg *msg, int sock)
 {
        struct ust_app *lta;
 
-       lta = malloc(sizeof(struct ust_app));
+       lta = zmalloc(sizeof(struct ust_app));
        if (lta == NULL) {
                PERROR("malloc");
                return -ENOMEM;
@@ -243,8 +359,11 @@ void ust_app_unregister(int sock)
                goto error;
        }
 
+       /* We got called because the socket was closed on the remote end. */
+       close(sock);
+       /* Using a flag because we still need "sock" as a key. */
+       lta->sock_closed = 1;
        call_rcu(&node->head, delete_ust_app_rcu);
-
 error:
        rcu_read_unlock();
        return;
@@ -264,6 +383,66 @@ unsigned long ust_app_list_count(void)
        return count;
 }
 
+/*
+ * Fill events array with all events name of all registered apps.
+ */
+int ust_app_list_events(struct lttng_event **events)
+{
+       int ret, handle;
+       size_t nbmem, count = 0;
+       struct cds_lfht_iter iter;
+       struct ust_app *app;
+       struct lttng_event *tmp;
+
+       nbmem = UST_APP_EVENT_LIST_SIZE;
+       tmp = zmalloc(nbmem * sizeof(struct lttng_event));
+       if (tmp == NULL) {
+               PERROR("zmalloc ust app events");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       rcu_read_lock();
+
+       cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) {
+               handle = ustctl_tracepoint_list(app->key.sock);
+               if (handle < 0) {
+                       ERR("UST app list events getting handle failed for app pid %d",
+                                       app->key.pid);
+                       continue;
+               }
+
+               while ((ret = ustctl_tracepoint_list_get(app->key.sock, handle,
+                                               tmp[count].name)) != -ENOENT) {
+                       if (count > nbmem) {
+                               DBG2("Reallocating event list from %zu to %zu bytes", nbmem,
+                                               nbmem + UST_APP_EVENT_LIST_SIZE);
+                               nbmem += UST_APP_EVENT_LIST_SIZE;
+                               tmp = realloc(tmp, nbmem);
+                               if (tmp == NULL) {
+                                       PERROR("realloc ust app events");
+                                       ret = -ENOMEM;
+                                       goto rcu_error;
+                               }
+                       }
+
+                       tmp[count].type = LTTNG_UST_TRACEPOINT;
+                       tmp[count].pid = app->key.pid;
+                       count++;
+               }
+       }
+
+       ret = count;
+       *events = tmp;
+
+       DBG2("UST app list events done (%zu events)", count);
+
+rcu_error:
+       rcu_read_unlock();
+error:
+       return ret;
+}
+
 /*
  * Free and clean all traceable apps of the global list.
  */
@@ -748,7 +927,7 @@ int ust_app_add_channel_all(struct ltt_ust_session *usess,
 
                /* Create session on the tracer side and add it to app session HT */
                ua_sess = create_ust_app_session(usess, app);
-               if (ret < 0) {
+               if (ua_sess == NULL) {
                        goto next;
                }
 
@@ -791,7 +970,7 @@ int ust_app_add_event_all(struct ltt_ust_session *usess,
 
                /* Create session on the tracer side and add it to app session HT */
                ua_sess = create_ust_app_session(usess, app);
-               if (ret < 0) {
+               if (ua_sess == NULL) {
                        goto next;
                }
 
@@ -829,15 +1008,17 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
 
        DBG("Starting tracing for ust app pid %d", app->key.pid);
 
+       rcu_read_lock();
+
        ua_sess = lookup_session_by_app(usess, app);
        if (ua_sess == NULL) {
                /* Only malloc can failed so something is really wrong */
-               goto error;
+               goto error_rcu_unlock;
        }
 
        ret = create_ust_app_metadata(ua_sess, usess->pathname, app);
        if (ret < 0) {
-               goto error;
+               goto error_rcu_unlock;
        }
 
        /* For each channel */
@@ -852,7 +1033,7 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
                        ustream = zmalloc(sizeof(*ustream));
                        if (ustream == NULL) {
                                PERROR("zmalloc ust stream");
-                               continue;
+                               goto error_rcu_unlock;
                        }
 
                        ret = ustctl_create_stream(app->key.sock, ua_chan->obj,
@@ -883,22 +1064,24 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
        /* Setup UST consumer socket and send fds to it */
        ret = ust_consumer_send_session(usess->consumer_fd, ua_sess);
        if (ret < 0) {
-               goto error;
+               goto error_rcu_unlock;
        }
 
        /* This start the UST tracing */
        ret = ustctl_start_session(app->key.sock, ua_sess->handle);
        if (ret < 0) {
                ERR("Error starting tracing for app pid: %d", app->key.pid);
-               goto error;
+               goto error_rcu_unlock;
        }
+       rcu_read_unlock();
 
        /* Quiescent wait after starting trace */
        ustctl_wait_quiescent(app->key.sock);
 
        return 0;
 
-error:
+error_rcu_unlock:
+       rcu_read_unlock();
        return -1;
 }
 
This page took 0.02903 seconds and 4 git commands to generate.