+static int create_ust_event_notifier(struct ust_app *app,
+ struct ust_app_event_notifier_rule *ua_event_notifier_rule)
+{
+ int ret = 0;
+ enum lttng_condition_status condition_status;
+ const struct lttng_condition *condition = NULL;
+ struct lttng_ust_abi_event_notifier event_notifier;
+ const struct lttng_event_rule *event_rule = NULL;
+ unsigned int capture_bytecode_count = 0, i;
+ enum lttng_condition_status cond_status;
+ enum lttng_event_rule_type event_rule_type;
+
+ health_code_update();
+ assert(app->event_notifier_group.object);
+
+ condition = lttng_trigger_get_const_condition(
+ ua_event_notifier_rule->trigger);
+ assert(condition);
+ assert(lttng_condition_get_type(condition) ==
+ LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES);
+
+ condition_status = lttng_condition_event_rule_matches_get_rule(
+ condition, &event_rule);
+ assert(condition_status == LTTNG_CONDITION_STATUS_OK);
+
+ assert(event_rule);
+
+ event_rule_type = lttng_event_rule_get_type(event_rule);
+ assert(event_rule_type == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT ||
+ event_rule_type == LTTNG_EVENT_RULE_TYPE_JUL_LOGGING ||
+ event_rule_type ==
+ LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING ||
+ event_rule_type ==
+ LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING);
+
+ init_ust_event_notifier_from_event_rule(event_rule, &event_notifier);
+ event_notifier.event.token = ua_event_notifier_rule->token;
+ event_notifier.error_counter_index = ua_event_notifier_rule->error_counter_index;
+
+ /* Create UST event notifier against the tracer. */
+ pthread_mutex_lock(&app->sock_lock);
+ ret = lttng_ust_ctl_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) {
+ ret = 0;
+ DBG3("UST app create event notifier failed. Application is dead: pid = %d, sock = %d",
+ app->pid, app->sock);
+ } else if (ret == -EAGAIN) {
+ ret = 0;
+ WARN("UST app create event notifier failed. Communication time out: pid = %d, sock = %d",
+ app->pid, app->sock);
+ } else {
+ ERR("UST app create event notifier '%s' failed with ret %d: pid = %d, sock = %d",
+ event_notifier.event.name, ret, app->pid,
+ app->sock);
+ }
+ goto error;
+ }
+
+ ua_event_notifier_rule->handle = ua_event_notifier_rule->obj->handle;
+
+ DBG2("UST app event notifier %s created successfully: app = '%s': pid = %d), object = %p",
+ event_notifier.event.name, app->name, app->pid,
+ 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;
+ }
+ }
+
+ /* Set the capture bytecodes. */
+ cond_status = lttng_condition_event_rule_matches_get_capture_descriptor_count(
+ condition, &capture_bytecode_count);
+ assert(cond_status == LTTNG_CONDITION_STATUS_OK);
+
+ for (i = 0; i < capture_bytecode_count; i++) {
+ const struct lttng_bytecode *capture_bytecode =
+ lttng_condition_event_rule_matches_get_capture_bytecode_at_index(
+ condition, i);
+
+ ret = set_ust_capture(app, capture_bytecode, i,
+ 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.
+ */
+static void shadow_copy_event(struct ust_app_event *ua_event,
+ struct ltt_ust_event *uevent)
+{
+ size_t exclusion_alloc_size;
+
+ strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name));
+ ua_event->name[sizeof(ua_event->name) - 1] = '\0';
+
+ ua_event->enabled = uevent->enabled;
+
+ /* Copy event attributes */
+ memcpy(&ua_event->attr, &uevent->attr, sizeof(ua_event->attr));
+
+ /* Copy filter bytecode */
+ if (uevent->filter) {
+ ua_event->filter = lttng_bytecode_copy(uevent->filter);
+ /* Filter might be NULL here in case of ENONEM. */
+ }
+
+ /* Copy exclusion data */
+ if (uevent->exclusion) {
+ exclusion_alloc_size = sizeof(struct lttng_event_exclusion) +
+ LTTNG_UST_ABI_SYM_NAME_LEN * uevent->exclusion->count;
+ ua_event->exclusion = zmalloc(exclusion_alloc_size);
+ if (ua_event->exclusion == NULL) {
+ PERROR("malloc");
+ } else {
+ memcpy(ua_event->exclusion, uevent->exclusion,
+ exclusion_alloc_size);
+ }
+ }
+}
+
+/*
+ * Copy data between an UST app channel and a LTT channel.
+ */
+static void shadow_copy_channel(struct ust_app_channel *ua_chan,