assert(registry);
assert(socket);
+ pthread_mutex_lock(®istry->lock);
+
+ /*
+ * Means that no metadata was assigned to the session. This can happens if
+ * no start has been done previously.
+ */
+ if (!registry->metadata_key) {
+ pthread_mutex_unlock(®istry->lock);
+ return 0;
+ }
+
/*
* 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.
- *
- * The ust app session mutex locked allows us to make this check without
- * the registry lock.
*/
if (registry->metadata_closed) {
+ pthread_mutex_unlock(®istry->lock);
return -EPIPE;
}
- pthread_mutex_lock(®istry->lock);
-
offset = registry->metadata_len_sent;
len = registry->metadata_len - registry->metadata_len_sent;
if (len == 0) {
end:
error:
+ if (ret_val) {
+ /*
+ * On error, flag the registry that the metadata is closed. We were unable
+ * to push anything and this means that either the consumer is not
+ * responding or the metadata cache has been destroyed on the consumer.
+ */
+ registry->metadata_closed = 1;
+ }
pthread_mutex_unlock(®istry->lock);
error_push:
free(metadata_str);
}
/*
- * For a given application and session, push metadata to consumer. The session
- * lock MUST be acquired here before calling this.
+ * For a given application and session, push metadata to consumer.
* Either sock or consumer is required : if sock is NULL, the default
* socket to send the metadata is retrieved from consumer, if sock
* is not NULL we use it to send the metadata.
+ * RCU read-side lock must be held while calling this function,
+ * therefore ensuring existance of registry.
*
* Return 0 on success else a negative error.
*/
assert(registry);
assert(consumer);
- rcu_read_lock();
+ pthread_mutex_lock(®istry->lock);
- /*
- * Means that no metadata was assigned to the session. This can happens if
- * no start has been done previously.
- */
- if (!registry->metadata_key) {
- ret_val = 0;
- goto end_rcu_unlock;
+ if (registry->metadata_closed) {
+ pthread_mutex_unlock(®istry->lock);
+ return -EPIPE;
}
/* Get consumer socket to use to push the metadata.*/
socket = consumer_find_socket_by_bitness(registry->bits_per_long,
consumer);
+ pthread_mutex_unlock(®istry->lock);
if (!socket) {
ret_val = -1;
- goto error_rcu_unlock;
+ goto error;
}
/*
pthread_mutex_unlock(socket->lock);
if (ret < 0) {
ret_val = ret;
- goto error_rcu_unlock;
+ goto error;
}
- rcu_read_unlock();
return 0;
-error_rcu_unlock:
- /*
- * On error, flag the registry that the metadata is closed. We were unable
- * to push anything and this means that either the consumer is not
- * responding or the metadata cache has been destroyed on the consumer.
- */
- registry->metadata_closed = 1;
-end_rcu_unlock:
- rcu_read_unlock();
+error:
+end:
return ret_val;
}
rcu_read_lock();
+ pthread_mutex_lock(®istry->lock);
+
if (!registry->metadata_key || registry->metadata_closed) {
ret = 0;
goto end;
*/
registry->metadata_closed = 1;
end:
+ pthread_mutex_unlock(®istry->lock);
rcu_read_unlock();
return ret;
}
pthread_mutex_lock(&ua_sess->lock);
registry = get_session_registry(ua_sess);
- if (registry && !registry->metadata_closed) {
+ if (registry) {
/* Push metadata for application before freeing the application. */
(void) push_metadata(registry, ua_sess->consumer);
* previous push metadata could have flag the metadata registry to
* close so don't send a close command if closed.
*/
- if (ua_sess->buffer_type != LTTNG_BUFFER_PER_UID &&
- !registry->metadata_closed) {
+ if (ua_sess->buffer_type != LTTNG_BUFFER_PER_UID) {
/* And ask to close it for this session registry. */
(void) close_metadata(registry, ua_sess->consumer);
}
registry = get_session_registry(ua_sess);
assert(registry);
+ pthread_mutex_lock(®istry->lock);
+
/* Metadata already exists for this registry or it was closed previously */
if (registry->metadata_key || registry->metadata_closed) {
ret = 0;
lttng_fd_put(LTTNG_FD_APPS, 1);
delete_ust_app_channel(-1, metadata, app);
error:
+ pthread_mutex_unlock(®istry->lock);
return ret;
}
DBG("PID %d unregistering with sock %d", lta->pid, sock);
/*
- * Perform "push metadata" and flush all application streams
- * before removing app from hash tables, ensuring proper
- * behavior of data_pending check.
+ * For per-PID buffers, perform "push metadata" and flush all
+ * application streams before removing app from hash tables,
+ * ensuring proper behavior of data_pending check.
* Remove sessions so they are not visible during deletion.
*/
cds_lfht_for_each_entry(lta->sessions->ht, &iter.iter, ua_sess,
continue;
}
- (void) ust_app_flush_app_session(lta, ua_sess);
+ if (ua_sess->buffer_type == LTTNG_BUFFER_PER_PID) {
+ (void) ust_app_flush_app_session(lta, ua_sess);
+ }
/*
* Add session to list for teardown. This is safe since at this point we
* session so the delete session will NOT push/close a second time.
*/
registry = get_session_registry(ua_sess);
- if (registry && !registry->metadata_closed) {
+ if (registry) {
/* Push metadata for application before freeing the application. */
(void) push_metadata(registry, ua_sess->consumer);
* previous push metadata could have flag the metadata registry to
* close so don't send a close command if closed.
*/
- if (ua_sess->buffer_type != LTTNG_BUFFER_PER_UID &&
- !registry->metadata_closed) {
+ if (ua_sess->buffer_type != LTTNG_BUFFER_PER_UID) {
/* And ask to close it for this session registry. */
(void) close_metadata(registry, ua_sess->consumer);
}
registry = get_session_registry(ua_sess);
assert(registry);
- if (!registry->metadata_closed) {
- /* Push metadata for application before freeing the application. */
- (void) push_metadata(registry, ua_sess->consumer);
- }
+ /* Push metadata for application before freeing the application. */
+ (void) push_metadata(registry, ua_sess->consumer);
end_unlock:
pthread_mutex_unlock(&ua_sess->lock);
/* Flushing buffers */
socket = consumer_find_socket_by_bitness(app->bits_per_long,
ua_sess->consumer);
- cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter, ua_chan,
- node.node) {
- health_code_update();
- assert(ua_chan->is_sent);
- ret = consumer_flush_channel(socket, ua_chan->key);
- if (ret) {
- ERR("Error flushing consumer channel");
- retval = -1;
- continue;
+
+ /* Flush buffers and push metadata. */
+ switch (ua_sess->buffer_type) {
+ case LTTNG_BUFFER_PER_PID:
+ cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter, ua_chan,
+ node.node) {
+ health_code_update();
+ assert(ua_chan->is_sent);
+ ret = consumer_flush_channel(socket, ua_chan->key);
+ if (ret) {
+ ERR("Error flushing consumer channel");
+ retval = -1;
+ continue;
+ }
}
+ break;
+ case LTTNG_BUFFER_PER_UID:
+ default:
+ assert(0);
+ break;
}
health_code_update();
pthread_mutex_unlock(&ua_sess->lock);
+
end_not_compatible:
rcu_read_unlock();
health_code_update();
}
/*
- * Flush buffers for a specific UST session and app.
+ * Flush buffers for all applications for a specific UST session.
+ * Called with UST session lock held.
*/
static
-int ust_app_flush_session(struct ust_app *app, struct ltt_ust_session *usess)
+int ust_app_flush_session(struct ltt_ust_session *usess)
{
int ret;
- struct ust_app_session *ua_sess;
- DBG("Flushing session buffers for ust app pid %d", app->pid);
+ DBG("Flushing session buffers for all ust apps");
rcu_read_lock();
- ua_sess = lookup_session_by_app(usess, app);
- if (ua_sess == NULL) {
- ret = -1;
- goto end_no_session;
+ /* Flush buffers and push metadata. */
+ switch (usess->buffer_type) {
+ case LTTNG_BUFFER_PER_UID:
+ {
+ struct buffer_reg_uid *reg;
+ struct lttng_ht_iter iter;
+
+ /* Flush all per UID buffers associated to that session. */
+ cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+ struct ust_registry_session *ust_session_reg;
+ struct buffer_reg_channel *reg_chan;
+ struct consumer_socket *socket;
+
+ /* Get consumer socket to use to push the metadata.*/
+ socket = consumer_find_socket_by_bitness(reg->bits_per_long,
+ usess->consumer);
+ if (!socket) {
+ /* Ignore request if no consumer is found for the session. */
+ continue;
+ }
+
+ cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
+ reg_chan, node.node) {
+ /*
+ * The following call will print error values so the return
+ * code is of little importance because whatever happens, we
+ * have to try them all.
+ */
+ (void) consumer_flush_channel(socket, reg_chan->consumer_key);
+ }
+
+ ust_session_reg = reg->registry->reg.ust;
+ /* Push metadata. */
+ (void) push_metadata(ust_session_reg, usess->consumer);
+ }
+ ret = 0;
+ break;
+ }
+ case LTTNG_BUFFER_PER_PID:
+ {
+ struct ust_app_session *ua_sess;
+ struct lttng_ht_iter iter;
+ struct ust_app *app;
+
+ cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+ ua_sess = lookup_session_by_app(usess, app);
+ if (ua_sess == NULL) {
+ continue;
+ }
+ (void) ust_app_flush_app_session(app, ua_sess);
+ }
+ break;
+ }
+ default:
+ assert(0);
+ break;
}
- ret = ust_app_flush_app_session(app, ua_sess);
end_no_session:
rcu_read_unlock();
/*
* Start tracing for the UST session.
+ * Called with UST session lock held.
*/
int ust_app_stop_trace_all(struct ltt_ust_session *usess)
{
}
}
- /* Flush buffers and push metadata (for UID buffers). */
- switch (usess->buffer_type) {
- case LTTNG_BUFFER_PER_UID:
- {
- struct buffer_reg_uid *reg;
-
- /* Flush all per UID buffers associated to that session. */
- cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
- struct ust_registry_session *ust_session_reg;
- struct buffer_reg_channel *reg_chan;
- struct consumer_socket *socket;
-
- /* Get consumer socket to use to push the metadata.*/
- socket = consumer_find_socket_by_bitness(reg->bits_per_long,
- usess->consumer);
- if (!socket) {
- /* Ignore request if no consumer is found for the session. */
- continue;
- }
-
- cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
- reg_chan, node.node) {
- /*
- * The following call will print error values so the return
- * code is of little importance because whatever happens, we
- * have to try them all.
- */
- (void) consumer_flush_channel(socket, reg_chan->consumer_key);
- }
-
- ust_session_reg = reg->registry->reg.ust;
- if (!ust_session_reg->metadata_closed) {
- /* Push metadata. */
- (void) push_metadata(ust_session_reg, usess->consumer);
- }
- }
-
- break;
- }
- case LTTNG_BUFFER_PER_PID:
- cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
- ret = ust_app_flush_session(app, usess);
- if (ret < 0) {
- /* Continue to next apps even on error */
- continue;
- }
- }
- break;
- default:
- assert(0);
- break;
- }
+ (void) ust_app_flush_session(usess);
rcu_read_unlock();