Fix: if relayd is unreachable, disable consumer for the session
[lttng-tools.git] / src / bin / lttng-sessiond / ust-app.c
index ee3b3406da781b1d488d17af5218933d2eefd265..0f553a671603845a6bdd40b9819505963d27c45b 100644 (file)
@@ -38,6 +38,7 @@
 #include "ust-app.h"
 #include "ust-consumer.h"
 #include "ust-ctl.h"
+#include "utils.h"
 
 /* Next available channel key. */
 static unsigned long next_channel_key;
@@ -307,9 +308,9 @@ void delete_ust_app_stream(int sock, struct ust_app_stream *stream)
 
 /*
  * We need to execute ht_destroy outside of RCU read-side critical
- * section, so we postpone its execution using call_rcu. It is simpler
- * than to change the semantic of the many callers of
- * delete_ust_app_channel().
+ * 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)
@@ -317,8 +318,8 @@ 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);
 
-       lttng_ht_destroy(ua_chan->ctx);
-       lttng_ht_destroy(ua_chan->events);
+       ht_cleanup_push(ua_chan->ctx);
+       ht_cleanup_push(ua_chan->events);
        free(ua_chan);
 }
 
@@ -583,9 +584,9 @@ end:
 
 /*
  * We need to execute ht_destroy outside of RCU read-side critical
- * section, so we postpone its execution using call_rcu. It is simpler
- * than to change the semantic of the many callers of
- * delete_ust_app_session().
+ * 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)
@@ -593,7 +594,7 @@ 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);
 
-       lttng_ht_destroy(ua_sess->channels);
+       ht_cleanup_push(ua_sess->channels);
        free(ua_sess);
 }
 
@@ -685,8 +686,8 @@ void delete_ust_app(struct ust_app *app)
                rcu_read_unlock();
        }
 
-       lttng_ht_destroy(app->sessions);
-       lttng_ht_destroy(app->ust_objd);
+       ht_cleanup_push(app->sessions);
+       ht_cleanup_push(app->ust_objd);
 
        /*
         * Wait until we have deleted the application from the sock hash table
@@ -1945,9 +1946,11 @@ static int do_consumer_create_channel(struct ltt_ust_session *usess,
         * Now get the channel from the consumer. This call wil populate the stream
         * list of that channel and set the ust objects.
         */
-       ret = ust_consumer_get_channel(socket, ua_chan);
-       if (ret < 0) {
-               goto error_destroy;
+       if (usess->consumer->enabled) {
+               ret = ust_consumer_get_channel(socket, ua_chan);
+               if (ret < 0) {
+                       goto error_destroy;
+               }
        }
 
        rcu_read_unlock();
@@ -2609,10 +2612,8 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
        ret = ust_consumer_ask_channel(ua_sess, metadata, consumer, socket,
                        registry);
        if (ret < 0) {
-               /*
-                * Safe because the metadata obj pointer is not set so the delete below
-                * will not put a FD back again.
-                */
+               /* Nullify the metadata key so we don't try to close it later on. */
+               registry->metadata_key = 0;
                goto error_consumer;
        }
 
@@ -2624,10 +2625,8 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
         */
        ret = consumer_setup_metadata(socket, metadata->key);
        if (ret < 0) {
-               /*
-                * Safe because the metadata obj pointer is not set so the delete below
-                * will not put a FD back again.
-                */
+               /* Nullify the metadata key so we don't try to close it later on. */
+               registry->metadata_key = 0;
                goto error_consumer;
        }
 
@@ -3155,9 +3154,9 @@ void ust_app_clean_list(void)
        rcu_read_unlock();
 
        /* Destroy is done only when the ht is empty */
-       lttng_ht_destroy(ust_app_ht);
-       lttng_ht_destroy(ust_app_ht_by_sock);
-       lttng_ht_destroy(ust_app_ht_by_notify_sock);
+       ht_cleanup_push(ust_app_ht);
+       ht_cleanup_push(ust_app_ht_by_sock);
+       ht_cleanup_push(ust_app_ht_by_notify_sock);
 }
 
 /*
@@ -4472,6 +4471,7 @@ static int reply_ust_register_channel(int sock, int sobjd, int cobjd,
                DBG("Application socket %d is being teardown. Abort event notify",
                                sock);
                ret = 0;
+               free(fields);
                goto error_rcu_unlock;
        }
 
@@ -4480,6 +4480,7 @@ static int reply_ust_register_channel(int sock, int sobjd, int cobjd,
        if (!ua_chan) {
                DBG("Application channel is being teardown. Abort event notify");
                ret = 0;
+               free(fields);
                goto error_rcu_unlock;
        }
 
@@ -4516,6 +4517,9 @@ static int reply_ust_register_channel(int sock, int sobjd, int cobjd,
        } else {
                /* Get current already assigned values. */
                type = chan_reg->header_type;
+               free(fields);
+               /* Set to NULL so the error path does not do a double free. */
+               fields = NULL;
        }
        /* Channel id is set during the object creation. */
        chan_id = chan_reg->chan_id;
@@ -4551,6 +4555,9 @@ error:
        pthread_mutex_unlock(&registry->lock);
 error_rcu_unlock:
        rcu_read_unlock();
+       if (ret) {
+               free(fields);
+       }
        return ret;
 }
 
@@ -4583,6 +4590,9 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
                DBG("Application socket %d is being teardown. Abort event notify",
                                sock);
                ret = 0;
+               free(sig);
+               free(fields);
+               free(model_emf_uri);
                goto error_rcu_unlock;
        }
 
@@ -4591,6 +4601,9 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
        if (!ua_chan) {
                DBG("Application channel is being teardown. Abort event notify");
                ret = 0;
+               free(sig);
+               free(fields);
+               free(model_emf_uri);
                goto error_rcu_unlock;
        }
 
@@ -4608,6 +4621,11 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
 
        pthread_mutex_lock(&registry->lock);
 
+       /*
+        * From this point on, this call acquires the ownership of the sig, fields
+        * and model_emf_uri meaning any free are done inside it if needed. These
+        * three variables MUST NOT be read/write after this.
+        */
        ret_code = ust_registry_create_event(registry, chan_reg_key,
                        sobjd, cobjd, name, sig, nr_fields, fields, loglevel,
                        model_emf_uri, ua_sess->buffer_type, &event_id);
@@ -4684,7 +4702,12 @@ int ust_app_recv_notify(int sock)
                        goto error;
                }
 
-               /* Add event to the UST registry coming from the notify socket. */
+               /*
+                * Add event to the UST registry coming from the notify socket. This
+                * call will free if needed the sig, fields and model_emf_uri. This
+                * code path loses the ownsership of these variables and transfer them
+                * to the this function.
+                */
                ret = add_event_ust_registry(sock, sobjd, cobjd, name, sig, nr_fields,
                                fields, loglevel, model_emf_uri);
                if (ret < 0) {
@@ -4712,6 +4735,11 @@ int ust_app_recv_notify(int sock)
                        goto error;
                }
 
+               /*
+                * The fields ownership are transfered to this function call meaning
+                * that if needed it will be freed. After this, it's invalid to access
+                * fields or clean it up.
+                */
                ret = reply_ust_register_channel(sock, sobjd, cobjd, nr_fields,
                                fields);
                if (ret < 0) {
@@ -4805,3 +4833,15 @@ close_socket:
                call_rcu(&obj->head, close_notify_sock_rcu);
        }
 }
+
+/*
+ * Destroy a ust app data structure and free its memory.
+ */
+void ust_app_destroy(struct ust_app *app)
+{
+       if (!app) {
+               return;
+       }
+
+       call_rcu(&app->pid_n.head, delete_ust_app_rcu);
+}
This page took 0.03136 seconds and 5 git commands to generate.