* Must be called with the registry lock held.
*
* On success, return the len of metadata pushed or else a negative value.
+ * Returning a -EPIPE return value means we could not send the metadata,
+ * but it can be caused by recoverable errors (e.g. the application has
+ * terminated concurrently).
*/
ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
struct consumer_socket *socket, int send_zero_data)
/*
* On a push metadata error either the consumer is dead or the
* metadata channel has been destroyed because its endpoint
- * might have died (e.g: relayd). If so, the metadata closed
- * flag is set to 1 so we deny pushing metadata again which is
- * not valid anymore on the consumer side.
+ * might have died (e.g: relayd), or because the application has
+ * exited. If so, the metadata closed flag is set to 1 so we
+ * deny pushing metadata again which is not valid anymore on the
+ * consumer side.
*/
if (registry->metadata_closed) {
return -EPIPE;
* of socket throughout this function.
*
* Return 0 on success else a negative error.
+ * Returning a -EPIPE return value means we could not send the metadata,
+ * but it can be caused by recoverable errors (e.g. the application has
+ * terminated concurrently).
*/
static int push_metadata(struct ust_registry_session *registry,
struct consumer_output *consumer)
pthread_mutex_lock(&ua_sess->lock);
+ assert(!ua_sess->deleted);
+ ua_sess->deleted = true;
+
registry = get_session_registry(ua_sess);
if (registry) {
/* Push metadata for application before freeing the application. */
*
* Return allocated filter or NULL on error.
*/
-static struct lttng_ust_filter_bytecode *alloc_copy_ust_app_filter(
- struct lttng_ust_filter_bytecode *orig_f)
+static struct lttng_filter_bytecode *copy_filter_bytecode(
+ struct lttng_filter_bytecode *orig_f)
{
- struct lttng_ust_filter_bytecode *filter = NULL;
+ struct lttng_filter_bytecode *filter = NULL;
/* Copy filter bytecode */
filter = zmalloc(sizeof(*filter) + orig_f->len);
if (!filter) {
- PERROR("zmalloc alloc ust app filter");
+ PERROR("zmalloc alloc filter bytecode");
goto error;
}
return filter;
}
+/*
+ * Create a liblttng-ust filter bytecode from given bytecode.
+ *
+ * Return allocated filter or NULL on error.
+ */
+static struct lttng_ust_filter_bytecode *create_ust_bytecode_from_bytecode(
+ struct lttng_filter_bytecode *orig_f)
+{
+ struct lttng_ust_filter_bytecode *filter = NULL;
+
+ /* Copy filter bytecode */
+ filter = zmalloc(sizeof(*filter) + orig_f->len);
+ if (!filter) {
+ PERROR("zmalloc alloc ust filter bytecode");
+ goto error;
+ }
+
+ assert(sizeof(struct lttng_filter_bytecode) ==
+ sizeof(struct lttng_ust_filter_bytecode));
+ memcpy(filter, orig_f, sizeof(*filter) + orig_f->len);
+error:
+ return filter;
+}
+
/*
* Find an ust_app using the sock and return it. RCU read side lock must be
* held before calling this helper function.
* Return an ust_app_event object or NULL on error.
*/
static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht,
- char *name, struct lttng_ust_filter_bytecode *filter, int loglevel,
+ char *name, struct lttng_filter_bytecode *filter, int loglevel,
const struct lttng_event_exclusion *exclusion)
{
struct lttng_ht_iter iter;
key.filter = filter;
key.loglevel = loglevel;
/* lttng_event_exclusion and lttng_ust_event_exclusion structures are similar */
- key.exclusion = (struct lttng_ust_event_exclusion *)exclusion;
+ key.exclusion = exclusion;
/* Lookup using the event name as hash and a custom match fct. */
cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed),
struct ust_app *app)
{
int ret;
+ struct lttng_ust_filter_bytecode *ust_bytecode = NULL;
health_code_update();
goto error;
}
- ret = ustctl_set_filter(app->sock, ua_event->filter,
+ ust_bytecode = create_ust_bytecode_from_bytecode(ua_event->filter);
+ if (!ust_bytecode) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
+ ret = ustctl_set_filter(app->sock, ust_bytecode,
ua_event->obj);
if (ret < 0) {
if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
error:
health_code_update();
+ free(ust_bytecode);
return ret;
}
+static
+struct lttng_ust_event_exclusion *create_ust_exclusion_from_exclusion(
+ struct lttng_event_exclusion *exclusion)
+{
+ struct lttng_ust_event_exclusion *ust_exclusion = NULL;
+ size_t exclusion_alloc_size = sizeof(struct lttng_ust_event_exclusion) +
+ LTTNG_UST_SYM_NAME_LEN * exclusion->count;
+
+ ust_exclusion = zmalloc(exclusion_alloc_size);
+ if (!ust_exclusion) {
+ PERROR("malloc");
+ goto end;
+ }
+
+ assert(sizeof(struct lttng_event_exclusion) ==
+ sizeof(struct lttng_ust_event_exclusion));
+ memcpy(ust_exclusion, exclusion, exclusion_alloc_size);
+end:
+ return ust_exclusion;
+}
+
/*
* Set event exclusions on the tracer.
*/
struct ust_app *app)
{
int ret;
+ struct lttng_ust_event_exclusion *ust_exclusion = NULL;
health_code_update();
goto error;
}
- ret = ustctl_set_exclusion(app->sock, ua_event->exclusion,
- ua_event->obj);
+ ust_exclusion = create_ust_exclusion_from_exclusion(
+ ua_event->exclusion);
+ if (!ust_exclusion) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto error;
+ }
+ ret = ustctl_set_exclusion(app->sock, ust_exclusion, ua_event->obj);
if (ret < 0) {
if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
ERR("UST app event %s exclusions failed for app (pid: %d) "
error:
health_code_update();
+ free(ust_exclusion);
return ret;
}
/* Copy filter bytecode */
if (uevent->filter) {
- ua_event->filter = alloc_copy_ust_app_filter(uevent->filter);
+ ua_event->filter = copy_filter_bytecode(uevent->filter);
/* Filter might be NULL here in case of ENONEM. */
}
/* Copy exclusion data */
if (uevent->exclusion) {
- exclusion_alloc_size = sizeof(struct lttng_ust_event_exclusion) +
+ exclusion_alloc_size = sizeof(struct lttng_event_exclusion) +
LTTNG_UST_SYM_NAME_LEN * uevent->exclusion->count;
ua_event->exclusion = zmalloc(exclusion_alloc_size);
if (ua_event->exclusion == NULL) {
*/
pthread_mutex_lock(&ua_sess->lock);
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ continue;
+ }
+
/*
* Normally, this is done in the delete session process which is
* executed in the call rcu below. However, upon registration we can't
assert(ua_sess);
pthread_mutex_lock(&ua_sess->lock);
+
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ continue;
+ }
+
if (!strncmp(uchan->name, DEFAULT_METADATA_NAME,
sizeof(uchan->name))) {
copy_channel_attr_to_ustctl(&ua_sess->metadata_attr, &uchan->attr);
pthread_mutex_lock(&ua_sess->lock);
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ continue;
+ }
+
/* Lookup channel in the ust app session */
lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
}
pthread_mutex_lock(&ua_sess->lock);
+
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ continue;
+ }
+
/* Lookup channel in the ust app session */
lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
pthread_mutex_lock(&ua_sess->lock);
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ goto end;
+ }
+
/* Upon restart, we skip the setup, already done */
if (ua_sess->started) {
goto skip_setup;
pthread_mutex_lock(&ua_sess->lock);
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ goto end_no_session;
+ }
+
/*
* If started = 0, it means that stop trace has been called for a session
* that was never started. It's possible since we can have a fail start
pthread_mutex_lock(&ua_sess->lock);
+ if (ua_sess->deleted) {
+ goto end_deleted;
+ }
+
health_code_update();
/* Flushing buffers */
health_code_update();
+end_deleted:
pthread_mutex_unlock(&ua_sess->lock);
end_not_compatible:
pthread_mutex_lock(&ua_sess->lock);
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ goto end;
+ }
+
/*
* We can iterate safely here over all UST app session since the create ust
* app session above made a shadow copy of the UST global domain from the
}
pthread_mutex_lock(&ua_sess->lock);
+
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ continue;
+ }
+
/* Lookup channel in the ust app session */
lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
}
pthread_mutex_lock(&ua_sess->lock);
+
+ if (ua_sess->deleted) {
+ ret = 0;
+ goto end_unlock;
+ }
+
/* Lookup channel in the ust app session */
lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
ua_chan_node = lttng_ht_iter_get_node_str(&iter);