X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-app.c;h=c30792c3c785e959968dc9c00434c0e12af1ec73;hb=00a620843422e5c972aee0ada2181b811fc81b92;hp=bdee8e64dc647e402dc252b3932a3dd695d50a33;hpb=99b1411c06926da6c87df96030d6d055076fc5e2;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index bdee8e64d..c30792c3c 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -426,8 +426,9 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, /* * Push metadata to consumer socket. * - * The socket lock MUST be acquired. - * The ust app session lock MUST be acquired. + * RCU read-side lock must be held to guarantee existance of socket. + * Must be called with the ust app session lock held. + * Must be called with the registry lock held. * * On success, return the len of metadata pushed or else a negative value. */ @@ -442,25 +443,22 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry, 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. + * 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. + * 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. */ if (registry->metadata_closed) { - pthread_mutex_unlock(®istry->lock); return -EPIPE; } @@ -489,29 +487,32 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry, 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) { /* - * There is an acceptable race here between the registry metadata key - * assignment and the creation on the consumer. The session daemon can - * concurrently push metadata for this registry while being created on - * the consumer since the metadata key of the registry is assigned - * *before* it is setup to avoid the consumer to ask for metadata that - * could possibly be not found in the session daemon. + * There is an acceptable race here between the registry + * metadata key assignment and the creation on the + * consumer. The session daemon can concurrently push + * metadata for this registry while being created on the + * consumer since the metadata key of the registry is + * assigned *before* it is setup to avoid the consumer + * to ask for metadata that could possibly be not found + * in the session daemon. * - * The metadata will get pushed either by the session being stopped or - * the consumer requesting metadata if that race is triggered. + * The metadata will get pushed either by the session + * being stopped or the consumer requesting metadata if + * that race is triggered. */ if (ret == -LTTCOMM_CONSUMERD_CHANNEL_FAIL) { ret = 0; } - /* Update back the actual metadata len sent since it failed here. */ - pthread_mutex_lock(®istry->lock); + /* + * Update back the actual metadata len sent since it + * failed here. + */ registry->metadata_len_sent -= len; - pthread_mutex_unlock(®istry->lock); ret_val = ret; goto error_push; } @@ -523,13 +524,14 @@ 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. + * 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); return ret_val; @@ -541,7 +543,8 @@ error_push: * 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. + * therefore ensuring existance of registry. It also ensures existance + * of socket throughout this function. * * Return 0 on success else a negative error. */ @@ -556,50 +559,36 @@ static int push_metadata(struct ust_registry_session *registry, assert(consumer); pthread_mutex_lock(®istry->lock); - if (registry->metadata_closed) { - pthread_mutex_unlock(®istry->lock); - return -EPIPE; + ret_val = -EPIPE; + goto error; } /* 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; } - /* - * TODO: Currently, we hold the socket lock around sampling of the next - * metadata segment to ensure we send metadata over the consumer socket in - * the correct order. This makes the registry lock nest inside the socket - * lock. - * - * Please note that this is a temporary measure: we should move this lock - * back into ust_consumer_push_metadata() when the consumer gets the - * ability to reorder the metadata it receives. - */ - pthread_mutex_lock(socket->lock); ret = ust_app_push_metadata(registry, socket, 0); - pthread_mutex_unlock(socket->lock); if (ret < 0) { ret_val = ret; goto error; } - + pthread_mutex_unlock(®istry->lock); return 0; error: -end: + pthread_mutex_unlock(®istry->lock); return ret_val; } /* * Send to the consumer a close metadata command for the given session. Once * done, the metadata channel is deleted and the session metadata pointer is - * nullified. The session lock MUST be acquired here unless the application is + * nullified. The session lock MUST be held unless the application is * in the destroy path. * * Return 0 on success else a negative value. @@ -1604,6 +1593,7 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, struct tm *timeinfo; char datetime[16]; int ret; + char tmp_shm_path[PATH_MAX]; /* Get date and time for unique app path */ time(&rawtime); @@ -1647,6 +1637,38 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, goto error; } + strncpy(ua_sess->root_shm_path, usess->root_shm_path, + sizeof(ua_sess->root_shm_path)); + ua_sess->root_shm_path[sizeof(ua_sess->root_shm_path) - 1] = '\0'; + strncpy(ua_sess->shm_path, usess->shm_path, + sizeof(ua_sess->shm_path)); + ua_sess->shm_path[sizeof(ua_sess->shm_path) - 1] = '\0'; + if (ua_sess->shm_path[0]) { + switch (ua_sess->buffer_type) { + case LTTNG_BUFFER_PER_PID: + ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path), + DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s", + app->name, app->pid, datetime); + break; + case LTTNG_BUFFER_PER_UID: + ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path), + DEFAULT_UST_TRACE_UID_PATH, + app->uid, app->bits_per_long); + break; + default: + assert(0); + goto error; + } + if (ret < 0) { + PERROR("sprintf UST shadow copy session"); + assert(0); + goto error; + } + strncat(ua_sess->shm_path, tmp_shm_path, + sizeof(ua_sess->shm_path) - strlen(ua_sess->shm_path) - 1); + ua_sess->shm_path[sizeof(ua_sess->shm_path) - 1] = '\0'; + } + /* Iterate over all channels in global domain. */ cds_lfht_for_each_entry(usess->domain_global.channels->ht, &iter.iter, uchan, node.node) { @@ -1738,7 +1760,8 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, * This is the create channel path meaning that if there is NO * registry available, we have to create one for this session. */ - ret = buffer_reg_pid_create(ua_sess->id, ®_pid); + ret = buffer_reg_pid_create(ua_sess->id, ®_pid, + ua_sess->root_shm_path, ua_sess->shm_path); if (ret < 0) { goto error; } @@ -1752,7 +1775,9 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, app->uint16_t_alignment, app->uint32_t_alignment, app->uint64_t_alignment, app->long_alignment, app->byte_order, app->version.major, - app->version.minor); + app->version.minor, reg_pid->root_shm_path, + reg_pid->shm_path, + ua_sess->euid, ua_sess->egid); if (ret < 0) { /* * reg_pid->registry->reg.ust is NULL upon error, so we need to @@ -1785,6 +1810,7 @@ error: * Return 0 on success or else a negative value. */ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, + struct ust_app_session *ua_sess, struct ust_app *app, struct buffer_reg_uid **regp) { int ret = 0; @@ -1802,7 +1828,8 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, * registry available, we have to create one for this session. */ ret = buffer_reg_uid_create(usess->id, app->bits_per_long, app->uid, - LTTNG_DOMAIN_UST, ®_uid); + LTTNG_DOMAIN_UST, ®_uid, + ua_sess->root_shm_path, ua_sess->shm_path); if (ret < 0) { goto error; } @@ -1816,7 +1843,8 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, app->uint16_t_alignment, app->uint32_t_alignment, app->uint64_t_alignment, app->long_alignment, app->byte_order, app->version.major, - app->version.minor); + app->version.minor, reg_uid->root_shm_path, + reg_uid->shm_path, usess->uid, usess->gid); if (ret < 0) { /* * reg_uid->registry->reg.ust is NULL upon error, so we need to @@ -1891,7 +1919,7 @@ static int create_ust_app_session(struct ltt_ust_session *usess, break; case LTTNG_BUFFER_PER_UID: /* Look for a global registry. If none exists, create one. */ - ret = setup_buffer_reg_uid(usess, app, NULL); + ret = setup_buffer_reg_uid(usess, ua_sess, app, NULL); if (ret < 0) { delete_ust_app_session(-1, ua_sess, app); goto error; @@ -3698,6 +3726,11 @@ int ust_app_create_channel_glb(struct ltt_ust_session *usess, */ continue; } + if (!trace_ust_pid_tracker_lookup(usess, app->pid)) { + /* Skip. */ + continue; + } + /* * Create session on the tracer side and add it to app session HT. Note * that if session exist, it will simply return a pointer to the ust @@ -4196,7 +4229,6 @@ int ust_app_flush_session(struct ltt_ust_session *usess) break; } -end_no_session: rcu_read_unlock(); health_code_update(); return ret; @@ -4326,46 +4358,26 @@ int ust_app_destroy_trace_all(struct ltt_ust_session *usess) return 0; } -/* - * Add channels/events from UST global domain to registered apps at sock. - */ -void ust_app_global_update(struct ltt_ust_session *usess, int sock) +static +void ust_app_global_create(struct ltt_ust_session *usess, struct ust_app *app) { int ret = 0; struct lttng_ht_iter iter, uiter; - struct ust_app *app; struct ust_app_session *ua_sess = NULL; struct ust_app_channel *ua_chan; struct ust_app_event *ua_event; struct ust_app_ctx *ua_ctx; + int is_created = 0; - assert(usess); - assert(sock >= 0); - - DBG2("UST app global update for app sock %d for session id %" PRIu64, sock, - usess->id); - - rcu_read_lock(); - - app = ust_app_find_by_sock(sock); - if (app == NULL) { - /* - * Application can be unregistered before so this is possible hence - * simply stopping the update. - */ - DBG3("UST app update failed to find app sock %d", sock); - goto error; - } - - if (!app->compatible) { - goto error; - } - - ret = create_ust_app_session(usess, app, &ua_sess, NULL); + ret = create_ust_app_session(usess, app, &ua_sess, &is_created); if (ret < 0) { /* Tracer is probably gone or ENOMEM. */ goto error; } + if (!is_created) { + /* App session already created. */ + goto end; + } assert(ua_sess); pthread_mutex_lock(&ua_sess->lock); @@ -4419,9 +4431,8 @@ void ust_app_global_update(struct ltt_ust_session *usess, int sock) DBG2("UST trace started for app pid %d", app->pid); } - +end: /* Everything went well at this point. */ - rcu_read_unlock(); return; error_unlock: @@ -4430,10 +4441,60 @@ error: if (ua_sess) { destroy_app_session(app, ua_sess); } - rcu_read_unlock(); return; } +static +void ust_app_global_destroy(struct ltt_ust_session *usess, struct ust_app *app) +{ + struct ust_app_session *ua_sess; + + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == NULL) { + return; + } + destroy_app_session(app, ua_sess); +} + +/* + * Add channels/events from UST global domain to registered apps at sock. + * + * Called with session lock held. + * Called with RCU read-side lock held. + */ +void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app) +{ + assert(usess); + + DBG2("UST app global update for app sock %d for session id %" PRIu64, + app->sock, usess->id); + + if (!app->compatible) { + return; + } + + if (trace_ust_pid_tracker_lookup(usess, app->pid)) { + ust_app_global_create(usess, app); + } else { + ust_app_global_destroy(usess, app); + } +} + +/* + * Called with session lock held. + */ +void ust_app_global_update_all(struct ltt_ust_session *usess) +{ + 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(usess, app); + } + rcu_read_unlock(); +} + /* * Add context to a specific channel for global UST domain. */