Fix: sessiond: assertion fails when getting name of trigger
[lttng-tools.git] / src / bin / lttng-sessiond / ust-app.c
index b30089dbc2fd6029f590adf8c05752ddda2d3225..5ab55ec29d3718b83a67135e3b6a155af8c74bfb 100644 (file)
 
 #include <common/compat/errno.h>
 #include <common/common.h>
+#include <common/hashtable/utils.h>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/event-rule/tracepoint.h>
+#include <lttng/condition/condition.h>
+#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/event-rule.h>
 #include <common/sessiond-comm/sessiond-comm.h>
 
 #include "buffer-registry.h"
@@ -313,6 +320,51 @@ void delete_ust_app_event(int sock, struct ust_app_event *ua_event,
        free(ua_event);
 }
 
+/*
+ * Delayed reclaim of a ust_app_event_notifier_rule object. This MUST be called
+ * through a call_rcu().
+ */
+static
+void free_ust_app_event_notifier_rule_rcu(struct rcu_head *head)
+{
+       struct ust_app_event_notifier_rule *obj = caa_container_of(
+                       head, struct ust_app_event_notifier_rule, rcu_head);
+
+       free(obj);
+}
+
+/*
+ * Delete ust app event notifier rule safely.
+ */
+static void delete_ust_app_event_notifier_rule(int sock,
+               struct ust_app_event_notifier_rule *ua_event_notifier_rule,
+               struct ust_app *app)
+{
+       int ret;
+
+       assert(ua_event_notifier_rule);
+
+       if (ua_event_notifier_rule->exclusion != NULL) {
+               free(ua_event_notifier_rule->exclusion);
+       }
+
+       if (ua_event_notifier_rule->obj != NULL) {
+               pthread_mutex_lock(&app->sock_lock);
+               ret = ustctl_release_object(sock, ua_event_notifier_rule->obj);
+               pthread_mutex_unlock(&app->sock_lock);
+               if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+                       ERR("Failed to release event notifier object: app = '%s' (ppid %d), ret = %d",
+                                       app->name, (int) app->ppid, ret);
+               }
+
+               free(ua_event_notifier_rule->obj);
+       }
+
+       lttng_event_rule_put(ua_event_notifier_rule->event_rule);
+       call_rcu(&ua_event_notifier_rule->rcu_head,
+                       free_ust_app_event_notifier_rule_rcu);
+}
+
 /*
  * Release ust data object of the given stream.
  *
@@ -898,6 +950,9 @@ void delete_ust_app(struct ust_app *app)
 {
        int ret, sock;
        struct ust_app_session *ua_sess, *tmp_ua_sess;
+       struct lttng_ht_iter iter;
+       struct ust_app_event_notifier_rule *event_notifier_rule;
+       bool event_notifier_write_fd_is_open;
 
        /*
         * The session list lock must be held during this function to guarantee
@@ -917,9 +972,23 @@ void delete_ust_app(struct ust_app *app)
                rcu_read_unlock();
        }
 
+       /* Remove the event notifier rules associated with this app. */
+       rcu_read_lock();
+       cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht,
+                       &iter.iter, event_notifier_rule, node.node) {
+               ret = lttng_ht_del(app->token_to_event_notifier_rule_ht, &iter);
+               assert(!ret);
+
+               delete_ust_app_event_notifier_rule(
+                               app->sock, event_notifier_rule, 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);
 
        /*
         * This could be NULL if the event notifier setup failed (e.g the app
@@ -941,7 +1010,16 @@ void delete_ust_app(struct ust_app *app)
                free(app->event_notifier_group.object);
        }
 
+       event_notifier_write_fd_is_open = lttng_pipe_is_write_open(
+                       app->event_notifier_group.event_pipe);
        lttng_pipe_destroy(app->event_notifier_group.event_pipe);
+       /*
+        * Release the file descriptors reserved for the event notifier pipe.
+        * The app could be destroyed before the write end of the pipe could be
+        * passed to the application (and closed). In that case, both file
+        * descriptors must be released.
+        */
+       lttng_fd_put(LTTNG_FD_APPS, event_notifier_write_fd_is_open ? 2 : 1);
 
        /*
         * Wait until we have deleted the application from the sock hash table
@@ -1147,6 +1225,57 @@ error:
        return NULL;
 }
 
+/*
+ * Allocate a new UST app event notifier rule.
+ */
+static struct ust_app_event_notifier_rule *alloc_ust_app_event_notifier_rule(
+               struct lttng_event_rule *event_rule, uint64_t token)
+{
+       enum lttng_event_rule_generate_exclusions_status
+                       generate_exclusion_status;
+       struct ust_app_event_notifier_rule *ua_event_notifier_rule;
+
+       ua_event_notifier_rule = zmalloc(sizeof(struct ust_app_event_notifier_rule));
+       if (ua_event_notifier_rule == NULL) {
+               PERROR("Failed to allocate ust_app_event_notifier_rule structure");
+               goto error;
+       }
+
+       ua_event_notifier_rule->enabled = 1;
+       ua_event_notifier_rule->token = token;
+       lttng_ht_node_init_u64(&ua_event_notifier_rule->node, token);
+
+       /* Get reference of the event rule. */
+       if (!lttng_event_rule_get(event_rule)) {
+               abort();
+       }
+
+       ua_event_notifier_rule->event_rule = event_rule;
+       ua_event_notifier_rule->filter = lttng_event_rule_get_filter_bytecode(event_rule);
+       generate_exclusion_status = lttng_event_rule_generate_exclusions(
+                       event_rule, &ua_event_notifier_rule->exclusion);
+       switch (generate_exclusion_status) {
+       case LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK:
+       case LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE:
+               break;
+       default:
+               /* Error occured. */
+               ERR("Failed to generate exclusions from event rule while allocating an event notifier rule");
+               goto error_put_event_rule;
+       }
+
+       DBG3("UST app event notifier rule allocated: token = %" PRIu64,
+                       ua_event_notifier_rule->token);
+
+       return ua_event_notifier_rule;
+
+error_put_event_rule:
+       lttng_event_rule_put(event_rule);
+error:
+       free(ua_event_notifier_rule);
+       return NULL;
+}
+
 /*
  * Alloc new UST app context.
  */
@@ -1319,6 +1448,35 @@ end:
        return event;
 }
 
+/*
+ * Look-up an event notifier rule based on its token id.
+ *
+ * Must be called with the RCU read lock held.
+ * Return an ust_app_event_notifier_rule object or NULL on error.
+ */
+static struct ust_app_event_notifier_rule *find_ust_app_event_notifier_rule(
+               struct lttng_ht *ht, uint64_t token)
+{
+       struct lttng_ht_iter iter;
+       struct lttng_ht_node_u64 *node;
+       struct ust_app_event_notifier_rule *event_notifier_rule = NULL;
+
+       assert(ht);
+
+       lttng_ht_lookup(ht, &token, &iter);
+       node = lttng_ht_iter_get_node_u64(&iter);
+       if (node == NULL) {
+               DBG2("UST app event notifier rule token not found: token = %" PRIu64,
+                               token);
+               goto end;
+       }
+
+       event_notifier_rule = caa_container_of(
+                       node, struct ust_app_event_notifier_rule, node);
+end:
+       return event_notifier_rule;
+}
+
 /*
  * Create the channel context on the tracer.
  *
@@ -1770,6 +1928,179 @@ error:
        return ret;
 }
 
+static int init_ust_event_notifier_from_event_rule(
+               const struct lttng_event_rule *rule,
+               struct lttng_ust_event_notifier *event_notifier)
+{
+       enum lttng_event_rule_status status;
+       enum lttng_loglevel_type loglevel_type;
+       enum lttng_ust_loglevel_type ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
+       int loglevel = -1, ret = 0;
+       const char *pattern;
+
+       /* For now only LTTNG_EVENT_RULE_TYPE_TRACEPOINT are supported. */
+       assert(lttng_event_rule_get_type(rule) ==
+                       LTTNG_EVENT_RULE_TYPE_TRACEPOINT);
+
+       memset(event_notifier, 0, sizeof(*event_notifier));
+
+       status = lttng_event_rule_tracepoint_get_pattern(rule, &pattern);
+       if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+               /* At this point, this is a fatal error. */
+               abort();
+       }
+
+       status = lttng_event_rule_tracepoint_get_log_level_type(
+                       rule, &loglevel_type);
+       if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+               /* At this point, this is a fatal error. */
+               abort();
+       }
+
+       switch (loglevel_type) {
+       case LTTNG_EVENT_LOGLEVEL_ALL:
+               ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
+               break;
+       case LTTNG_EVENT_LOGLEVEL_RANGE:
+               ust_loglevel_type = LTTNG_UST_LOGLEVEL_RANGE;
+               break;
+       case LTTNG_EVENT_LOGLEVEL_SINGLE:
+               ust_loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE;
+               break;
+       default:
+               /* Unknown log level specification type. */
+               abort();
+       }
+
+       if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
+               status = lttng_event_rule_tracepoint_get_log_level(
+                               rule, &loglevel);
+               assert(status == LTTNG_EVENT_RULE_STATUS_OK);
+       }
+
+       event_notifier->event.instrumentation = LTTNG_UST_TRACEPOINT;
+       ret = lttng_strncpy(event_notifier->event.name, pattern,
+                           LTTNG_UST_SYM_NAME_LEN - 1);
+       if (ret) {
+               ERR("Failed to copy event rule pattern to notifier: pattern = '%s' ",
+                               pattern);
+               goto end;
+       }
+
+       event_notifier->event.loglevel_type = ust_loglevel_type;
+       event_notifier->event.loglevel = loglevel;
+end:
+       return ret;
+}
+
+/*
+ * Create the specified event notifier against the user space tracer of a
+ * given application.
+ */
+static int create_ust_event_notifier(struct ust_app *app,
+               struct ust_app_event_notifier_rule *ua_event_notifier_rule)
+{
+       int ret = 0;
+       struct lttng_ust_event_notifier event_notifier;
+
+       health_code_update();
+       assert(app->event_notifier_group.object);
+
+       ret = init_ust_event_notifier_from_event_rule(
+                       ua_event_notifier_rule->event_rule, &event_notifier);
+       if (ret) {
+               ERR("Failed to initialize UST event notifier from event rule: app = '%s' (ppid: %d)",
+                               app->name, app->ppid);
+               goto error;
+       }
+
+       event_notifier.event.token = ua_event_notifier_rule->token;
+
+       /* Create UST event notifier against the tracer. */
+       pthread_mutex_lock(&app->sock_lock);
+       ret = ustctl_create_event_notifier(app->sock, &event_notifier,
+                       app->event_notifier_group.object,
+                       &ua_event_notifier_rule->obj);
+       pthread_mutex_unlock(&app->sock_lock);
+       if (ret < 0) {
+               if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+                       ERR("Error ustctl create event notifier: name = '%s', app = '%s' (ppid: %d), ret = %d",
+                                       event_notifier.event.name, app->name,
+                                       app->ppid, ret);
+               } else {
+                       /*
+                        * This is normal behavior, an application can die
+                        * during the creation process. Don't report an error so
+                        * the execution can continue normally.
+                        */
+                       ret = 0;
+                       DBG3("UST app create event notifier failed (application is dead): app = '%s' (ppid = %d)",
+                                       app->name, app->ppid);
+               }
+
+               goto error;
+       }
+
+       ua_event_notifier_rule->handle = ua_event_notifier_rule->obj->handle;
+
+       DBG2("UST app event notifier %s created successfully: app = '%s' (ppid: %d), object: %p",
+                       event_notifier.event.name, app->name, app->ppid,
+                       ua_event_notifier_rule->obj);
+
+       health_code_update();
+
+       /* Set filter if one is present. */
+       if (ua_event_notifier_rule->filter) {
+               ret = set_ust_object_filter(app, ua_event_notifier_rule->filter,
+                               ua_event_notifier_rule->obj);
+               if (ret < 0) {
+                       goto error;
+               }
+       }
+
+       /* Set exclusions for the event. */
+       if (ua_event_notifier_rule->exclusion) {
+               ret = set_ust_object_exclusions(app,
+                               ua_event_notifier_rule->exclusion,
+                               ua_event_notifier_rule->obj);
+               if (ret < 0) {
+                       goto error;
+               }
+       }
+
+       /*
+        * We now need to explicitly enable the event, since it
+        * is disabled at creation.
+        */
+       ret = enable_ust_object(app, ua_event_notifier_rule->obj);
+       if (ret < 0) {
+               /*
+                * 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.
+                */
+               switch (ret) {
+               case -LTTNG_UST_ERR_PERM:
+                       /* Code flow problem. */
+                       abort();
+               case -LTTNG_UST_ERR_EXIST:
+                       /* It's OK for our use case. */
+                       ret = 0;
+                       break;
+               default:
+                       break;
+               }
+
+               goto error;
+       }
+
+       ua_event_notifier_rule->enabled = true;
+
+error:
+       health_code_update();
+       return ret;
+}
+
 /*
  * Copy data between an UST app event and a LTT event.
  */
@@ -3139,6 +3470,7 @@ error:
 /*
  * Create UST app event and create it on the tracer side.
  *
+ * Must be called with the RCU read side lock held.
  * Called with ust app session mutex held.
  */
 static
@@ -3178,8 +3510,8 @@ int create_ust_app_event(struct ust_app_session *ua_sess,
 
        add_unique_ust_app_event(ua_chan, ua_event);
 
-       DBG2("UST app create event %s for PID %d completed", ua_event->name,
-                       app->pid);
+       DBG2("UST app create event completed: app = '%s' (ppid: %d)",
+                       app->name, app->ppid);
 
 end:
        return ret;
@@ -3190,6 +3522,59 @@ error:
        return ret;
 }
 
+/*
+ * Create UST app event notifier rule and create it on the tracer side.
+ *
+ * Must be called with the RCU read side lock held.
+ * Called with ust app session mutex held.
+ */
+static
+int create_ust_app_event_notifier_rule(struct lttng_event_rule *rule,
+               struct ust_app *app, uint64_t token)
+{
+       int ret = 0;
+       struct ust_app_event_notifier_rule *ua_event_notifier_rule;
+
+       ua_event_notifier_rule = alloc_ust_app_event_notifier_rule(rule, token);
+       if (ua_event_notifier_rule == NULL) {
+               ret = -ENOMEM;
+               goto end;
+       }
+
+       /* Create it on the tracer side. */
+       ret = create_ust_event_notifier(app, ua_event_notifier_rule);
+       if (ret < 0) {
+               /*
+                * Not found previously means that it does not exist on the
+                * tracer. If the application reports that the event existed,
+                * it means there is a bug in the sessiond or lttng-ust
+                * (or corruption, etc.)
+                */
+               if (ret == -LTTNG_UST_ERR_EXIST) {
+                       ERR("Tracer for application reported that an event notifier being created already exists: "
+                                       "token = \"%" PRIu64 "\", pid = %d, ppid = %d, uid = %d, gid = %d",
+                                       token,
+                                       app->pid, app->ppid, app->uid,
+                                       app->gid);
+               }
+               goto error;
+       }
+
+       lttng_ht_add_unique_u64(app->token_to_event_notifier_rule_ht,
+                       &ua_event_notifier_rule->node);
+
+       DBG2("UST app create token event rule completed: app = '%s' (ppid: %d), token = %" PRIu64,
+                       app->name, app->ppid, token);
+
+end:
+       return ret;
+
+error:
+       /* The RCU read side lock is already being held by the caller. */
+       delete_ust_app_event_notifier_rule(-1, ua_event_notifier_rule, app);
+       return ret;
+}
+
 /*
  * Create UST metadata and open it on the tracer side.
  *
@@ -3333,6 +3718,7 @@ error:
  */
 struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
 {
+       int ret;
        struct ust_app *lta = NULL;
        struct lttng_pipe *event_notifier_event_source_pipe = NULL;
 
@@ -3351,6 +3737,18 @@ struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
                goto error;
        }
 
+       /*
+        * Reserve the two file descriptors of the event source pipe. The write
+        * end will be closed once it is passed to the application, at which
+        * point a single 'put' will be performed.
+        */
+       ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+       if (ret) {
+               ERR("Failed to reserve two file descriptors for the event source pipe while creating a new application instance: app = '%s' (ppid: %d)",
+                               msg->name, (int) msg->ppid);
+               goto error;
+       }
+
        event_notifier_event_source_pipe = lttng_pipe_open(FD_CLOEXEC);
        if (!event_notifier_event_source_pipe) {
                PERROR("Failed to open application event source pipe: '%s' (ppid = %d)",
@@ -3384,6 +3782,7 @@ struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
        lta->ust_objd = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
        lta->ust_sessions_objd = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
        lta->notify_sock = -1;
+       lta->token_to_event_notifier_rule_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
 
        /* Copy name and make sure it's NULL terminated. */
        strncpy(lta->name, msg->name, sizeof(lta->name));
@@ -3407,6 +3806,7 @@ struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
 
 error_free_pipe:
        lttng_pipe_destroy(event_notifier_event_source_pipe);
+       lttng_fd_put(LTTNG_FD_APPS, 2);
 error:
        return NULL;
 }
@@ -3509,6 +3909,19 @@ int ust_app_setup_event_notifier_group(struct ust_app *app)
                goto error;
        }
 
+       ret = lttng_pipe_write_close(app->event_notifier_group.event_pipe);
+       if (ret) {
+               ERR("Failed to close write end of the application's event source pipe: app = '%s' (ppid = %d)",
+                               app->name, app->ppid);
+               goto error;
+       }
+
+       /*
+        * Release the file descriptor that was reserved for the write-end of
+        * the pipe.
+        */
+       lttng_fd_put(LTTNG_FD_APPS, 1);
+
        lttng_ret = notification_thread_command_add_tracer_event_source(
                        notification_thread_handle,
                        lttng_pipe_get_readfd(app->event_notifier_group.event_pipe),
@@ -3938,16 +4351,12 @@ void ust_app_clean_list(void)
        if (ust_app_ht_by_notify_sock) {
                cds_lfht_for_each_entry(ust_app_ht_by_notify_sock->ht, &iter.iter, app,
                                notify_sock_n.node) {
-                       struct cds_lfht_node *node;
-                       struct ust_app *app;
-
-                       node = cds_lfht_iter_get_node(&iter.iter);
-                       if (!node) {
-                               continue;
-                       }
+                       /*
+                        * Assert that all notifiers are gone as all triggers
+                        * are unregistered prior to this clean-up.
+                        */
+                       assert(lttng_ht_get_count(app->token_to_event_notifier_rule_ht) == 0);
 
-                       app = container_of(node, struct ust_app,
-                                       notify_sock_n.node);
                        ust_app_notify_sock_unregister(app->notify_sock);
                }
        }
@@ -5074,6 +5483,149 @@ end:
        return ret;
 }
 
+/* Called with RCU read-side lock held. */
+static
+void ust_app_synchronize_event_notifier_rules(struct ust_app *app)
+{
+       int ret = 0;
+       enum lttng_error_code ret_code;
+       enum lttng_trigger_status t_status;
+       struct lttng_ht_iter app_trigger_iter;
+       struct lttng_triggers *triggers = NULL;
+       struct ust_app_event_notifier_rule *event_notifier_rule;
+       unsigned int count, i;
+
+       /*
+        * Currrently, registering or unregistering a trigger with an
+        * event rule condition causes a full synchronization of the event
+        * notifiers.
+        *
+        * The first step attempts to add an event notifier for all registered
+        * triggers that apply to the user space tracers. Then, the
+        * application's event notifiers rules are all checked against the list
+        * of registered triggers. Any event notifier that doesn't have a
+        * matching trigger can be assumed to have been disabled.
+        *
+        * All of this is inefficient, but is put in place to get the feature
+        * rolling as it is simpler at this moment. It will be optimized Soon™
+        * to allow the state of enabled
+        * event notifiers to be synchronized in a piece-wise way.
+        */
+
+       /* Get all triggers using uid 0 (root) */
+       ret_code = notification_thread_command_list_triggers(
+                       notification_thread_handle, 0, &triggers);
+       if (ret_code != LTTNG_OK) {
+               ret = -1;
+               goto end;
+       }
+
+       assert(triggers);
+
+       t_status = lttng_triggers_get_count(triggers, &count);
+       if (t_status != LTTNG_TRIGGER_STATUS_OK) {
+               ret = -1;
+               goto end;
+       }
+
+       for (i = 0; i < count; i++) {
+               struct lttng_condition *condition;
+               struct lttng_event_rule *event_rule;
+               struct lttng_trigger *trigger;
+               const struct ust_app_event_notifier_rule *looked_up_event_notifier_rule;
+               enum lttng_condition_status condition_status;
+               uint64_t token;
+
+               trigger = lttng_triggers_borrow_mutable_at_index(triggers, i);
+               assert(trigger);
+
+               token = lttng_trigger_get_tracer_token(trigger);
+               condition = lttng_trigger_get_condition(trigger);
+
+               if (lttng_condition_get_type(condition) != LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) {
+                       /* Does not apply */
+                       continue;
+               }
+
+               condition_status = lttng_condition_event_rule_borrow_rule_mutable(condition, &event_rule);
+               assert(condition_status == LTTNG_CONDITION_STATUS_OK);
+
+               if (lttng_event_rule_get_domain_type(event_rule) == LTTNG_DOMAIN_KERNEL) {
+                       /* Skip kernel related triggers. */
+                       continue;
+               }
+
+               /*
+                * Find or create the associated token event rule. The caller
+                * holds the RCU read lock, so this is safe to call without
+                * explicitly acquiring it here.
+                */
+               looked_up_event_notifier_rule = find_ust_app_event_notifier_rule(
+                               app->token_to_event_notifier_rule_ht, token);
+               if (!looked_up_event_notifier_rule) {
+                       ret = create_ust_app_event_notifier_rule(event_rule, app, token);
+                       if (ret < 0) {
+                               goto end;
+                       }
+               }
+       }
+
+       rcu_read_lock();
+       /* Remove all unknown event sources from the app. */
+       cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht,
+                       &app_trigger_iter.iter, event_notifier_rule,
+                       node.node) {
+               const uint64_t app_token = event_notifier_rule->token;
+               bool found = false;
+
+               /*
+                * Check if the app event trigger still exists on the
+                * notification side.
+                */
+               for (i = 0; i < count; i++) {
+                       uint64_t notification_thread_token;
+                       const struct lttng_trigger *trigger =
+                                       lttng_triggers_get_at_index(
+                                                       triggers, i);
+
+                       assert(trigger);
+
+                       notification_thread_token =
+                                       lttng_trigger_get_tracer_token(trigger);
+
+                       if (notification_thread_token == app_token) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               if (found) {
+                       /* Still valid. */
+                       continue;
+               }
+
+               /*
+                * This trigger was unregistered, disable it on the tracer's
+                * side.
+                */
+               ret = lttng_ht_del(app->token_to_event_notifier_rule_ht,
+                               &app_trigger_iter);
+               assert(ret == 0);
+
+               /* Callee logs errors. */
+               (void) disable_ust_object(app, event_notifier_rule->obj);
+
+               delete_ust_app_event_notifier_rule(
+                               app->sock, event_notifier_rule, app);
+       }
+
+       rcu_read_unlock();
+
+end:
+       lttng_triggers_destroy(triggers);
+       return;
+}
+
 /*
  * The caller must ensure that the application is compatible and is tracked
  * by the process attribute trackers.
@@ -5231,6 +5783,30 @@ void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app)
        }
 }
 
+/*
+ * Add all event notifiers to an application.
+ *
+ * Called with session lock held.
+ * Called with RCU read-side lock held.
+ */
+void ust_app_global_update_event_notifier_rules(struct ust_app *app)
+{
+       DBG2("UST application global event notifier rules update: app = '%s' (ppid: %d)",
+                       app->name, app->ppid);
+
+       if (!app->compatible) {
+               return;
+       }
+
+       if (app->event_notifier_group.object == NULL) {
+               WARN("UST app global update of event notifiers for app skipped since communication handle is null: app = '%s' (ppid: %d)",
+                               app->name, app->ppid);
+               return;
+       }
+
+       ust_app_synchronize_event_notifier_rules(app);
+}
+
 /*
  * Called with session lock held.
  */
@@ -5246,6 +5822,19 @@ void ust_app_global_update_all(struct ltt_ust_session *usess)
        rcu_read_unlock();
 }
 
+void ust_app_global_update_all_event_notifier_rules(void)
+{
+       struct lttng_ht_iter iter;
+       struct ust_app *app;
+
+       rcu_read_lock();
+       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+               ust_app_global_update_event_notifier_rules(app);
+       }
+
+       rcu_read_unlock();
+}
+
 /*
  * Add context to a specific channel for global UST domain.
  */
This page took 0.030969 seconds and 4 git commands to generate.