X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-app.c;h=fdcad1c304ab0c717fb3f619b812de6d17433b31;hb=331744e34f56a5aec69b05d356d6901e67926acc;hp=979ae7c3c7659c97997649b5d477c68ecf47e7da;hpb=31fa4745f181bd1bdbceb89fbe27e130f5b4e2b9;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 979ae7c3c..fdcad1c30 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -367,18 +368,84 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, free(ua_chan); } +/* + * Push metadata to consumer socket. The socket lock MUST be acquired. + * + * On success, return the len of metadata pushed or else a negative value. + */ +ssize_t ust_app_push_metadata(struct ust_registry_session *registry, + struct consumer_socket *socket, int send_zero_data) +{ + int ret; + char *metadata_str = NULL; + size_t len, offset; + ssize_t ret_val; + + assert(registry); + assert(socket); + /* Should never be 0 which is the initial state. */ + assert(registry->metadata_key); + + pthread_mutex_lock(®istry->lock); + + offset = registry->metadata_len_sent; + len = registry->metadata_len - registry->metadata_len_sent; + if (len == 0) { + DBG3("No metadata to push for metadata key %" PRIu64, + registry->metadata_key); + ret_val = len; + if (send_zero_data) { + DBG("No metadata to push"); + goto push_data; + } + goto end; + } + + /* Allocate only what we have to send. */ + metadata_str = zmalloc(len); + if (!metadata_str) { + PERROR("zmalloc ust app metadata string"); + ret_val = -ENOMEM; + goto error; + } + /* Copy what we haven't send out. */ + memcpy(metadata_str, registry->metadata + offset, len); + registry->metadata_len_sent += len; + +push_data: + pthread_mutex_unlock(®istry->lock); + ret = consumer_push_metadata(socket, registry->metadata_key, + metadata_str, len, offset); + if (ret < 0) { + ret_val = ret; + goto error_push; + } + + free(metadata_str); + return len; + +end: +error: + pthread_mutex_unlock(®istry->lock); +error_push: + free(metadata_str); + return ret_val; +} + /* * For a given application and session, push metadata to consumer. The session * lock MUST be acquired here before calling this. + * 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. * * Return 0 on success else a negative error. */ static int push_metadata(struct ust_registry_session *registry, struct consumer_output *consumer) { - int ret; - char *metadata_str = NULL; - size_t len, offset; + int ret_val; + ssize_t ret; struct consumer_socket *socket; assert(registry); @@ -391,7 +458,7 @@ static int push_metadata(struct ust_registry_session *registry, * no start has been done previously. */ if (!registry->metadata_key) { - ret = 0; + ret_val = 0; goto error_rcu_unlock; } @@ -399,7 +466,7 @@ static int push_metadata(struct ust_registry_session *registry, socket = consumer_find_socket_by_bitness(registry->bits_per_long, consumer); if (!socket) { - ret = -1; + ret_val = -1; goto error_rcu_unlock; } @@ -414,54 +481,19 @@ static int push_metadata(struct ust_registry_session *registry, * ability to reorder the metadata it receives. */ pthread_mutex_lock(socket->lock); - pthread_mutex_lock(®istry->lock); - - offset = registry->metadata_len_sent; - len = registry->metadata_len - registry->metadata_len_sent; - if (len == 0) { - DBG3("No metadata to push for metadata key %" PRIu64, - registry->metadata_key); - ret = 0; - goto error_reg_unlock; - } - assert(len > 0); - - /* Allocate only what we have to send. */ - metadata_str = zmalloc(len); - if (!metadata_str) { - PERROR("zmalloc ust app metadata string"); - ret = -ENOMEM; - goto error_reg_unlock; - } - /* Copy what we haven't send out. */ - memcpy(metadata_str, registry->metadata + offset, len); - - pthread_mutex_unlock(®istry->lock); - - ret = consumer_push_metadata(socket, registry->metadata_key, - metadata_str, len, offset); + ret = ust_app_push_metadata(registry, socket, 0); + pthread_mutex_unlock(socket->lock); if (ret < 0) { - pthread_mutex_unlock(socket->lock); + ret_val = ret; goto error_rcu_unlock; } - /* Update len sent of the registry. */ - pthread_mutex_lock(®istry->lock); - registry->metadata_len_sent += len; - pthread_mutex_unlock(®istry->lock); - pthread_mutex_unlock(socket->lock); - rcu_read_unlock(); - free(metadata_str); return 0; -error_reg_unlock: - pthread_mutex_unlock(®istry->lock); - pthread_mutex_unlock(socket->lock); error_rcu_unlock: rcu_read_unlock(); - free(metadata_str); - return ret; + return ret_val; } /* @@ -2481,6 +2513,14 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, goto error; } + /* + * Keep metadata key so we can identify it on the consumer side. Assign it + * to the registry *before* we ask the consumer so we avoid the race of the + * consumer requesting the metadata and the ask_channel call on our side + * did not returned yet. + */ + registry->metadata_key = metadata->key; + /* * Ask the metadata channel creation to the consumer. The metadata object * will be created by the consumer and kept their. However, the stream is @@ -2514,9 +2554,6 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, goto error_consumer; } - /* Keep metadata key so we can identify it on the consumer side. */ - registry->metadata_key = metadata->key; - DBG2("UST metadata with key %" PRIu64 " created for app pid %d", metadata->key, app->pid);