X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fbin%2Flttng-sessiond%2Fust-app.cpp;h=fcc4267ad5ea8360ae6e139bada338f6f1dff83e;hb=HEAD;hp=90b0b65b729d5614f89665b839886a939ebaaa90;hpb=66cefebdc240cbae0bc79594305f509b0779fa98;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-app.cpp b/src/bin/lttng-sessiond/ust-app.cpp index 90b0b65b7..d993b7b44 100644 --- a/src/bin/lttng-sessiond/ust-app.cpp +++ b/src/bin/lttng-sessiond/ust-app.cpp @@ -19,7 +19,6 @@ #include "lttng-ust-ctl.hpp" #include "lttng-ust-error.hpp" #include "notification-thread-commands.hpp" -#include "rotate.hpp" #include "session.hpp" #include "ust-app.hpp" #include "ust-consumer.hpp" @@ -33,6 +32,7 @@ #include #include #include +#include #include #include @@ -66,7 +66,7 @@ struct lttng_ht *ust_app_ht; struct lttng_ht *ust_app_ht_by_sock; struct lttng_ht *ust_app_ht_by_notify_sock; -static int ust_app_flush_app_session(struct ust_app *app, struct ust_app_session *ua_sess); +static int ust_app_flush_app_session(ust_app& app, ust_app_session& ua_sess); /* Next available channel key. Access under next_channel_key_lock. */ static uint64_t _next_channel_key; @@ -181,14 +181,12 @@ static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key) { struct ust_app_event *event; const struct ust_app_ht_key *key; - int ev_loglevel_value; LTTNG_ASSERT(node); LTTNG_ASSERT(_key); event = caa_container_of(node, struct ust_app_event, node.node); key = (ust_app_ht_key *) _key; - ev_loglevel_value = event->attr.loglevel; /* Match the 4 elements of the key: name, filter, loglevel, exclusions */ @@ -198,18 +196,12 @@ static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key) } /* Event loglevel. */ - if (ev_loglevel_value != key->loglevel_type) { - if (event->attr.loglevel_type == LTTNG_UST_ABI_LOGLEVEL_ALL && - key->loglevel_type == 0 && ev_loglevel_value == -1) { - /* - * Match is accepted. This is because on event creation, the - * loglevel is set to -1 if the event loglevel type is ALL so 0 and - * -1 are accepted for this loglevel type since 0 is the one set by - * the API when receiving an enable event. - */ - } else { - goto no_match; - } + if (!loglevels_match(event->attr.loglevel_type, + event->attr.loglevel, + key->loglevel_type, + key->loglevel_value, + LTTNG_UST_ABI_LOGLEVEL_ALL)) { + goto no_match; } /* One of the filters is NULL, fail. */ @@ -264,7 +256,8 @@ static void add_unique_ust_app_event(struct ust_app_channel *ua_chan, struct ust ht = ua_chan->events; key.name = event->attr.name; key.filter = event->filter; - key.loglevel_type = (lttng_ust_abi_loglevel_type) event->attr.loglevel; + key.loglevel_type = (lttng_ust_abi_loglevel_type) event->attr.loglevel_type; + key.loglevel_value = event->attr.loglevel; key.exclusion = event->exclusion; node_ptr = cds_lfht_add_unique(ht->ht, @@ -331,6 +324,12 @@ static void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx, struct ust_ } free(ua_ctx->obj); } + + if (ua_ctx->ctx.ctx == LTTNG_UST_ABI_CONTEXT_APP_CONTEXT) { + free(ua_ctx->ctx.u.app_ctx.provider_name); + free(ua_ctx->ctx.u.app_ctx.ctx_name); + } + free(ua_ctx); } @@ -505,7 +504,7 @@ static void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan return; } - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; session = session_find_by_id(ua_chan->session->tracing_id); if (!session || !session->ust_session) { /* @@ -548,7 +547,6 @@ static void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan uchan->per_pid_closed_app_lost += lost; end: - rcu_read_unlock(); if (session) { session_put(session); } @@ -1034,24 +1032,24 @@ static void delete_ust_app(struct ust_app *app) /* Wipe sessions */ cds_list_for_each_entry_safe (ua_sess, tmp_ua_sess, &app->teardown_head, teardown_node) { /* Free every object in the session and the session. */ - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; delete_ust_app_session(sock, ua_sess, app); - rcu_read_unlock(); } /* Remove the event notifier rules associated with this app. */ - rcu_read_lock(); - cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht, - &iter.iter, - event_notifier_rule, - node.node) { - ret = lttng_ht_del(app->token_to_event_notifier_rule_ht, &iter); - LTTNG_ASSERT(!ret); + { + lttng::urcu::read_lock_guard read_lock; - delete_ust_app_event_notifier_rule(app->sock, event_notifier_rule, app); - } + cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht, + &iter.iter, + event_notifier_rule, + node.node) { + ret = lttng_ht_del(app->token_to_event_notifier_rule_ht, &iter); + LTTNG_ASSERT(!ret); - rcu_read_unlock(); + delete_ust_app_event_notifier_rule(app->sock, event_notifier_rule, app); + } + } lttng_ht_destroy(app->sessions); lttng_ht_destroy(app->ust_sessions_objd); @@ -1501,6 +1499,7 @@ error: static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht, const char *name, const struct lttng_bytecode *filter, + lttng_ust_abi_loglevel_type loglevel_type, int loglevel_value, const struct lttng_event_exclusion *exclusion) { @@ -1515,7 +1514,8 @@ static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht, /* Setup key for event lookup. */ key.name = name; key.filter = filter; - key.loglevel_type = (lttng_ust_abi_loglevel_type) loglevel_value; + key.loglevel_type = loglevel_type; + key.loglevel_value = loglevel_value; /* lttng_event_exclusion and lttng_ust_event_exclusion structures are similar */ key.exclusion = exclusion; @@ -2566,7 +2566,7 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, LTTNG_ASSERT(ua_sess); LTTNG_ASSERT(app); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; reg_pid = buffer_reg_pid_find(ua_sess->id); if (!reg_pid) { @@ -2614,7 +2614,6 @@ end: *regp = reg_pid; } error: - rcu_read_unlock(); return ret; } @@ -2636,7 +2635,7 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, LTTNG_ASSERT(usess); LTTNG_ASSERT(app); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; reg_uid = buffer_reg_uid_find(usess->id, app->abi.bits_per_long, app->uid); if (!reg_uid) { @@ -2690,7 +2689,6 @@ end: *regp = reg_uid; } error: - rcu_read_unlock(); return ret; } @@ -3053,7 +3051,7 @@ static int do_consumer_create_channel(struct ltt_ust_session *usess, LTTNG_ASSERT(ua_chan); LTTNG_ASSERT(registry); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; health_code_update(); /* Get the right consumer socket for the application. */ @@ -3108,7 +3106,6 @@ static int do_consumer_create_channel(struct ltt_ust_session *usess, } } - rcu_read_unlock(); return 0; error_destroy: @@ -3125,7 +3122,6 @@ error_ask: lttng_fd_put(LTTNG_FD_APPS, 1); error: health_code_update(); - rcu_read_unlock(); return ret; } @@ -3581,7 +3577,7 @@ static int create_channel_per_pid(struct ust_app *app, DBG("UST app creating channel %s with per PID buffers", ua_chan->name); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; registry = get_session_registry(ua_sess); /* The UST app session lock is held, registry shall not be null. */ @@ -3649,7 +3645,6 @@ error_remove_from_registry: } } error: - rcu_read_unlock(); if (session) { session_put(session); } @@ -4076,6 +4071,8 @@ struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock) goto error_free_pipe; } + urcu_ref_init(<a->ref); + lta->event_notifier_group.event_pipe = event_notifier_event_source_pipe; lta->ppid = msg->ppid; @@ -4139,7 +4136,7 @@ void ust_app_add(struct ust_app *app) app->registration_time = time(nullptr); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; /* * On a re-registration, we want to kick out the previous registration of @@ -4169,8 +4166,6 @@ void ust_app_add(struct ust_app *app) app->notify_sock, app->v_major, app->v_minor); - - rcu_read_unlock(); } /* @@ -4335,30 +4330,12 @@ error: return ret; } -/* - * Unregister app by removing it from the global traceable app list and freeing - * the data struct. - * - * The socket is already closed at this point so no close to sock. - */ -void ust_app_unregister(int sock) +static void ust_app_unregister(ust_app& app) { - struct ust_app *lta; - struct lttng_ht_node_ulong *node; - struct lttng_ht_iter ust_app_sock_iter; struct lttng_ht_iter iter; struct ust_app_session *ua_sess; - int ret; - - rcu_read_lock(); - - /* Get the node reference for a call_rcu */ - lttng_ht_lookup(ust_app_ht_by_sock, (void *) ((unsigned long) sock), &ust_app_sock_iter); - node = lttng_ht_iter_get_node_ulong(&ust_app_sock_iter); - LTTNG_ASSERT(node); - lta = lttng::utils::container_of(node, &ust_app::sock_n); - DBG("PID %d unregistering with sock %d", lta->pid, sock); + lttng::urcu::read_lock_guard read_lock; /* * For per-PID buffers, perform "push metadata" and flush all @@ -4366,25 +4343,24 @@ void ust_app_unregister(int sock) * 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, node.node) { - ret = lttng_ht_del(lta->sessions, &iter); - if (ret) { + cds_lfht_for_each_entry (app.sessions->ht, &iter.iter, ua_sess, node.node) { + const auto del_ret = lttng_ht_del(app.sessions, &iter); + if (del_ret) { /* The session was already removed so scheduled for teardown. */ continue; } if (ua_sess->buffer_type == LTTNG_BUFFER_PER_PID) { - (void) ust_app_flush_app_session(lta, ua_sess); + (void) ust_app_flush_app_session(app, *ua_sess); } /* * Add session to list for teardown. This is safe since at this point we * are the only one using this list. */ - pthread_mutex_lock(&ua_sess->lock); + lttng::pthread::lock_guard ust_app_session_lock(ua_sess->lock); if (ua_sess->deleted) { - pthread_mutex_unlock(&ua_sess->lock); continue; } @@ -4427,22 +4403,17 @@ void ust_app_unregister(int sock) locked_registry.reset(); } } - cds_list_add(&ua_sess->teardown_node, <a->teardown_head); - pthread_mutex_unlock(&ua_sess->lock); + cds_list_add(&ua_sess->teardown_node, &app.teardown_head); } - /* Remove application from PID hash table */ - ret = lttng_ht_del(ust_app_ht_by_sock, &ust_app_sock_iter); - LTTNG_ASSERT(!ret); - /* * Remove application from notify hash table. The thread handling the * notify socket could have deleted the node so ignore on error because * either way it's valid. The close of that socket is handled by the * apps_notify_thread. */ - iter.iter.node = <a->notify_sock_n.node; + iter.iter.node = &app.notify_sock_n.node; (void) lttng_ht_del(ust_app_ht_by_notify_sock, &iter); /* @@ -4450,17 +4421,47 @@ void ust_app_unregister(int sock) * add replace during app registration because the PID can be reassigned by * the OS. */ - iter.iter.node = <a->pid_n.node; - ret = lttng_ht_del(ust_app_ht, &iter); - if (ret) { - DBG3("Unregister app by PID %d failed. This can happen on pid reuse", lta->pid); + iter.iter.node = &app.pid_n.node; + if (lttng_ht_del(ust_app_ht, &iter)) { + DBG3("Unregister app by PID %d failed. This can happen on pid reuse", app.pid); } +} - /* Free memory */ - call_rcu(<a->pid_n.head, delete_ust_app_rcu); +/* + * Unregister app by removing it from the global traceable app list and freeing + * the data struct. + * + * The socket is already closed at this point, so there is no need to close it. + */ +void ust_app_unregister_by_socket(int sock_fd) +{ + struct ust_app *app; + struct lttng_ht_node_ulong *node; + struct lttng_ht_iter ust_app_sock_iter; + int ret; - rcu_read_unlock(); - return; + lttng::urcu::read_lock_guard read_lock; + + /* Get the node reference for a call_rcu */ + lttng_ht_lookup(ust_app_ht_by_sock, (void *) ((unsigned long) sock_fd), &ust_app_sock_iter); + node = lttng_ht_iter_get_node_ulong(&ust_app_sock_iter); + assert(node); + + app = caa_container_of(node, struct ust_app, sock_n); + + DBG_FMT("Application unregistering after socket activity: pid={}, socket_fd={}", + app->pid, + sock_fd); + + /* Remove application from socket hash table */ + ret = lttng_ht_del(ust_app_ht_by_sock, &ust_app_sock_iter); + assert(!ret); + + /* + * The socket is closed: release its reference to the application + * to trigger its eventual teardown. + */ + ust_app_put(app); } /* @@ -4482,75 +4483,49 @@ int ust_app_list_events(struct lttng_event **events) goto error; } - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - struct lttng_ust_abi_tracepoint_iter uiter; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + struct lttng_ust_abi_tracepoint_iter uiter; - health_code_update(); + health_code_update(); - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - pthread_mutex_lock(&app->sock_lock); - handle = lttng_ust_ctl_tracepoint_list(app->sock); - if (handle < 0) { - if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) { - ERR("UST app list events getting handle failed for app pid %d", - app->pid); + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; } - pthread_mutex_unlock(&app->sock_lock); - continue; - } - - while ((ret = lttng_ust_ctl_tracepoint_list_get(app->sock, handle, &uiter)) != - -LTTNG_UST_ERR_NOENT) { - /* Handle ustctl error. */ - if (ret < 0) { - int release_ret; - if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { - ERR("UST app tp list get failed for app %d with ret %d", - app->sock, - ret); - } else { - DBG3("UST app tp list get failed. Application is dead"); - break; - } - free(tmp_event); - release_ret = lttng_ust_ctl_release_handle(app->sock, handle); - if (release_ret < 0 && release_ret != -LTTNG_UST_ERR_EXITING && - release_ret != -EPIPE) { - ERR("Error releasing app handle for app %d with ret %d", - app->sock, - release_ret); + pthread_mutex_lock(&app->sock_lock); + handle = lttng_ust_ctl_tracepoint_list(app->sock); + if (handle < 0) { + if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) { + ERR("UST app list events getting handle failed for app pid %d", + app->pid); } pthread_mutex_unlock(&app->sock_lock); - goto rcu_error; + continue; } - health_code_update(); - if (count >= nbmem) { - /* In case the realloc fails, we free the memory */ - struct lttng_event *new_tmp_event; - size_t new_nbmem; - - new_nbmem = nbmem << 1; - DBG2("Reallocating event list from %zu to %zu entries", - nbmem, - new_nbmem); - new_tmp_event = (lttng_event *) realloc( - tmp_event, new_nbmem * sizeof(struct lttng_event)); - if (new_tmp_event == nullptr) { + while ((ret = lttng_ust_ctl_tracepoint_list_get( + app->sock, handle, &uiter)) != -LTTNG_UST_ERR_NOENT) { + /* Handle ustctl error. */ + if (ret < 0) { int release_ret; - PERROR("realloc ust app events"); + if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { + ERR("UST app tp list get failed for app %d with ret %d", + app->sock, + ret); + } else { + DBG3("UST app tp list get failed. Application is dead"); + break; + } + free(tmp_event); - ret = -ENOMEM; release_ret = lttng_ust_ctl_release_handle(app->sock, handle); if (release_ret < 0 && @@ -4560,39 +4535,78 @@ int ust_app_list_events(struct lttng_event **events) app->sock, release_ret); } + pthread_mutex_unlock(&app->sock_lock); goto rcu_error; } - /* Zero the new memory */ - memset(new_tmp_event + nbmem, - 0, - (new_nbmem - nbmem) * sizeof(struct lttng_event)); - nbmem = new_nbmem; - tmp_event = new_tmp_event; + + health_code_update(); + if (count >= nbmem) { + /* In case the realloc fails, we free the memory */ + struct lttng_event *new_tmp_event; + size_t new_nbmem; + + new_nbmem = nbmem << 1; + DBG2("Reallocating event list from %zu to %zu entries", + nbmem, + new_nbmem); + new_tmp_event = (lttng_event *) realloc( + tmp_event, new_nbmem * sizeof(struct lttng_event)); + if (new_tmp_event == nullptr) { + int release_ret; + + PERROR("realloc ust app events"); + free(tmp_event); + ret = -ENOMEM; + release_ret = lttng_ust_ctl_release_handle( + app->sock, handle); + if (release_ret < 0 && + release_ret != -LTTNG_UST_ERR_EXITING && + release_ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", + app->sock, + release_ret); + } + + pthread_mutex_unlock(&app->sock_lock); + goto rcu_error; + } + /* Zero the new memory */ + memset(new_tmp_event + nbmem, + 0, + (new_nbmem - nbmem) * sizeof(struct lttng_event)); + nbmem = new_nbmem; + tmp_event = new_tmp_event; + } + + memcpy(tmp_event[count].name, + uiter.name, + LTTNG_UST_ABI_SYM_NAME_LEN); + tmp_event[count].loglevel = uiter.loglevel; + tmp_event[count].type = + (enum lttng_event_type) LTTNG_UST_ABI_TRACEPOINT; + tmp_event[count].pid = app->pid; + tmp_event[count].enabled = -1; + count++; } - memcpy(tmp_event[count].name, uiter.name, LTTNG_UST_ABI_SYM_NAME_LEN); - tmp_event[count].loglevel = uiter.loglevel; - tmp_event[count].type = (enum lttng_event_type) LTTNG_UST_ABI_TRACEPOINT; - tmp_event[count].pid = app->pid; - tmp_event[count].enabled = -1; - count++; - } - ret = lttng_ust_ctl_release_handle(app->sock, handle); - pthread_mutex_unlock(&app->sock_lock); - if (ret < 0) { - if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { - DBG3("Error releasing app handle. Application died: pid = %d, sock = %d", - app->pid, - app->sock); - } else if (ret == -EAGAIN) { - WARN("Error releasing app handle. Communication time out: pid = %d, sock = %d", - app->pid, - app->sock); - } else { - ERR("Error releasing app handle with ret %d: pid = %d, sock = %d", - ret, - app->pid, - app->sock); + + ret = lttng_ust_ctl_release_handle(app->sock, handle); + pthread_mutex_unlock(&app->sock_lock); + if (ret < 0) { + if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { + DBG3("Error releasing app handle. Application died: pid = %d, sock = %d", + app->pid, + app->sock); + } else if (ret == -EAGAIN) { + WARN("Error releasing app handle. Communication time out: pid = %d, sock = %d", + app->pid, + app->sock); + } else { + ERR("Error releasing app handle with ret %d: pid = %d, sock = %d", + ret, + app->pid, + app->sock); + } } } } @@ -4603,7 +4617,6 @@ int ust_app_list_events(struct lttng_event **events) DBG2("UST app list events done (%zu events)", count); rcu_error: - rcu_read_unlock(); error: health_code_update(); return ret; @@ -4628,114 +4641,129 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) goto error; } - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - struct lttng_ust_abi_field_iter uiter; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + struct lttng_ust_abi_field_iter uiter; - health_code_update(); + health_code_update(); - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - pthread_mutex_lock(&app->sock_lock); - handle = lttng_ust_ctl_tracepoint_field_list(app->sock); - if (handle < 0) { - if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) { - ERR("UST app list field getting handle failed for app pid %d", - app->pid); + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; } - pthread_mutex_unlock(&app->sock_lock); - continue; - } - while ((ret = lttng_ust_ctl_tracepoint_field_list_get(app->sock, handle, &uiter)) != - -LTTNG_UST_ERR_NOENT) { - /* Handle ustctl error. */ - if (ret < 0) { - int release_ret; - - if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { - ERR("UST app tp list field failed for app %d with ret %d", - app->sock, - ret); - } else { - DBG3("UST app tp list field failed. Application is dead"); - break; + pthread_mutex_lock(&app->sock_lock); + handle = lttng_ust_ctl_tracepoint_field_list(app->sock); + if (handle < 0) { + if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) { + ERR("UST app list field getting handle failed for app pid %d", + app->pid); } - free(tmp_event); - release_ret = lttng_ust_ctl_release_handle(app->sock, handle); pthread_mutex_unlock(&app->sock_lock); - if (release_ret < 0 && release_ret != -LTTNG_UST_ERR_EXITING && - release_ret != -EPIPE) { - ERR("Error releasing app handle for app %d with ret %d", - app->sock, - release_ret); - } - goto rcu_error; + continue; } - health_code_update(); - if (count >= nbmem) { - /* In case the realloc fails, we free the memory */ - struct lttng_event_field *new_tmp_event; - size_t new_nbmem; - - new_nbmem = nbmem << 1; - DBG2("Reallocating event field list from %zu to %zu entries", - nbmem, - new_nbmem); - new_tmp_event = (lttng_event_field *) realloc( - tmp_event, new_nbmem * sizeof(struct lttng_event_field)); - if (new_tmp_event == nullptr) { + while ((ret = lttng_ust_ctl_tracepoint_field_list_get( + app->sock, handle, &uiter)) != -LTTNG_UST_ERR_NOENT) { + /* Handle ustctl error. */ + if (ret < 0) { int release_ret; - PERROR("realloc ust app event fields"); + if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { + ERR("UST app tp list field failed for app %d with ret %d", + app->sock, + ret); + } else { + DBG3("UST app tp list field failed. Application is dead"); + break; + } + free(tmp_event); - ret = -ENOMEM; release_ret = lttng_ust_ctl_release_handle(app->sock, handle); pthread_mutex_unlock(&app->sock_lock); - if (release_ret && release_ret != -LTTNG_UST_ERR_EXITING && + if (release_ret < 0 && + release_ret != -LTTNG_UST_ERR_EXITING && release_ret != -EPIPE) { ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret); } + goto rcu_error; } - /* Zero the new memory */ - memset(new_tmp_event + nbmem, - 0, - (new_nbmem - nbmem) * sizeof(struct lttng_event_field)); - nbmem = new_nbmem; - tmp_event = new_tmp_event; + + health_code_update(); + if (count >= nbmem) { + /* In case the realloc fails, we free the memory */ + struct lttng_event_field *new_tmp_event; + size_t new_nbmem; + + new_nbmem = nbmem << 1; + DBG2("Reallocating event field list from %zu to %zu entries", + nbmem, + new_nbmem); + new_tmp_event = (lttng_event_field *) realloc( + tmp_event, + new_nbmem * sizeof(struct lttng_event_field)); + if (new_tmp_event == nullptr) { + int release_ret; + + PERROR("realloc ust app event fields"); + free(tmp_event); + ret = -ENOMEM; + release_ret = lttng_ust_ctl_release_handle( + app->sock, handle); + pthread_mutex_unlock(&app->sock_lock); + if (release_ret && + release_ret != -LTTNG_UST_ERR_EXITING && + release_ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", + app->sock, + release_ret); + } + + goto rcu_error; + } + + /* Zero the new memory */ + memset(new_tmp_event + nbmem, + 0, + (new_nbmem - nbmem) * + sizeof(struct lttng_event_field)); + nbmem = new_nbmem; + tmp_event = new_tmp_event; + } + + memcpy(tmp_event[count].field_name, + uiter.field_name, + LTTNG_UST_ABI_SYM_NAME_LEN); + /* Mapping between these enums matches 1 to 1. */ + tmp_event[count].type = (enum lttng_event_field_type) uiter.type; + tmp_event[count].nowrite = uiter.nowrite; + + memcpy(tmp_event[count].event.name, + uiter.event_name, + LTTNG_UST_ABI_SYM_NAME_LEN); + tmp_event[count].event.loglevel = uiter.loglevel; + tmp_event[count].event.type = LTTNG_EVENT_TRACEPOINT; + tmp_event[count].event.pid = app->pid; + tmp_event[count].event.enabled = -1; + count++; } - memcpy(tmp_event[count].field_name, - uiter.field_name, - LTTNG_UST_ABI_SYM_NAME_LEN); - /* Mapping between these enums matches 1 to 1. */ - tmp_event[count].type = (enum lttng_event_field_type) uiter.type; - tmp_event[count].nowrite = uiter.nowrite; - - memcpy(tmp_event[count].event.name, - uiter.event_name, - LTTNG_UST_ABI_SYM_NAME_LEN); - tmp_event[count].event.loglevel = uiter.loglevel; - tmp_event[count].event.type = LTTNG_EVENT_TRACEPOINT; - tmp_event[count].event.pid = app->pid; - tmp_event[count].event.enabled = -1; - count++; - } - ret = lttng_ust_ctl_release_handle(app->sock, handle); - pthread_mutex_unlock(&app->sock_lock); - if (ret < 0 && ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { - ERR("Error releasing app handle for app %d with ret %d", app->sock, ret); + ret = lttng_ust_ctl_release_handle(app->sock, handle); + pthread_mutex_unlock(&app->sock_lock); + if (ret < 0 && ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", + app->sock, + ret); + } } } @@ -4745,7 +4773,6 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) DBG2("UST app list event fields done (%zu events)", count); rcu_error: - rcu_read_unlock(); error: health_code_update(); return ret; @@ -4762,10 +4789,10 @@ void ust_app_clean_list() DBG2("UST app cleaning registered apps hash table"); - rcu_read_lock(); - /* Cleanup notify socket hash table */ if (ust_app_ht_by_notify_sock) { + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry ( ust_app_ht_by_notify_sock->ht, &iter.iter, app, notify_sock_n.node) { /* @@ -4773,29 +4800,21 @@ void ust_app_clean_list() * are unregistered prior to this clean-up. */ LTTNG_ASSERT(lttng_ht_get_count(app->token_to_event_notifier_rule_ht) == 0); - ust_app_notify_sock_unregister(app->notify_sock); } } - if (ust_app_ht) { - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - ret = lttng_ht_del(ust_app_ht, &iter); - LTTNG_ASSERT(!ret); - call_rcu(&app->pid_n.head, delete_ust_app_rcu); - } - } - /* Cleanup socket hash table */ if (ust_app_ht_by_sock) { + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry (ust_app_ht_by_sock->ht, &iter.iter, app, sock_n.node) { ret = lttng_ht_del(ust_app_ht_by_sock, &iter); LTTNG_ASSERT(!ret); + ust_app_put(app); } } - rcu_read_unlock(); - /* Destroy is done only when the ht is empty */ if (ust_app_ht) { lttng_ht_destroy(ust_app_ht); @@ -4845,42 +4864,43 @@ int ust_app_disable_channel_glb(struct ltt_ust_session *usess, struct ltt_ust_ch uchan->name, usess->id); - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - /* For every registered applications */ - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - struct lttng_ht_iter uiter; - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - ua_sess = lookup_session_by_app(usess, app); - if (ua_sess == nullptr) { - continue; - } + /* For every registered applications */ + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + struct lttng_ht_iter uiter; + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; + } + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == nullptr) { + continue; + } - /* Get channel */ - lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter); - ua_chan_node = lttng_ht_iter_get_node_str(&uiter); - /* If the session if found for the app, the channel must be there */ - LTTNG_ASSERT(ua_chan_node); + /* Get channel */ + lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter); + ua_chan_node = lttng_ht_iter_get_node_str(&uiter); + /* If the session if found for the app, the channel must be there */ + LTTNG_ASSERT(ua_chan_node); - ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node); - /* The channel must not be already disabled */ - LTTNG_ASSERT(ua_chan->enabled); + ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node); + /* The channel must not be already disabled */ + LTTNG_ASSERT(ua_chan->enabled); - /* Disable channel onto application */ - ret = disable_ust_app_channel(ua_sess, ua_chan, app); - if (ret < 0) { - /* XXX: We might want to report this error at some point... */ - continue; + /* Disable channel onto application */ + ret = disable_ust_app_channel(ua_sess, ua_chan, app); + if (ret < 0) { + /* XXX: We might want to report this error at some point... */ + continue; + } } } - rcu_read_unlock(); return ret; } @@ -4899,31 +4919,32 @@ int ust_app_enable_channel_glb(struct ltt_ust_session *usess, struct ltt_ust_cha uchan->name, usess->id); - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - /* For every registered applications */ - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - ua_sess = lookup_session_by_app(usess, app); - if (ua_sess == nullptr) { - continue; - } + /* For every registered applications */ + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; + } + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == nullptr) { + continue; + } - /* Enable channel onto application */ - ret = enable_ust_app_channel(ua_sess, uchan, app); - if (ret < 0) { - /* XXX: We might want to report this error at some point... */ - continue; + /* Enable channel onto application */ + ret = enable_ust_app_channel(ua_sess, uchan, app); + if (ret < 0) { + /* XXX: We might want to report this error at some point... */ + continue; + } } } - rcu_read_unlock(); return ret; } @@ -4949,58 +4970,62 @@ int ust_app_disable_event_glb(struct ltt_ust_session *usess, uchan->name, usess->id); - rcu_read_lock(); - - /* For all registered applications */ - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - ua_sess = lookup_session_by_app(usess, app); - if (ua_sess == nullptr) { - /* Next app */ - continue; - } + { + lttng::urcu::read_lock_guard read_lock; - /* 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); - if (ua_chan_node == nullptr) { - DBG2("Channel %s not found in session id %" PRIu64 " for app pid %d." - "Skipping", - uchan->name, - usess->id, - app->pid); - continue; - } - ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node); + /* For all registered applications */ + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; + } + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == nullptr) { + /* Next app */ + continue; + } - ua_event = find_ust_app_event(ua_chan->events, - uevent->attr.name, - uevent->filter, - uevent->attr.loglevel, - uevent->exclusion); - if (ua_event == nullptr) { - DBG2("Event %s not found in channel %s for app pid %d." - "Skipping", - uevent->attr.name, - uchan->name, - app->pid); - 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); + if (ua_chan_node == nullptr) { + DBG2("Channel %s not found in session id %" PRIu64 + " for app pid %d." + "Skipping", + uchan->name, + usess->id, + app->pid); + continue; + } + ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node); + + ua_event = find_ust_app_event( + ua_chan->events, + uevent->attr.name, + uevent->filter, + (enum lttng_ust_abi_loglevel_type) uevent->attr.loglevel_type, + uevent->attr.loglevel, + uevent->exclusion); + if (ua_event == nullptr) { + DBG2("Event %s not found in channel %s for app pid %d." + "Skipping", + uevent->attr.name, + uchan->name, + app->pid); + continue; + } - ret = disable_ust_app_event(ua_event, app); - if (ret < 0) { - /* XXX: Report error someday... */ - continue; + ret = disable_ust_app_event(ua_event, app); + if (ret < 0) { + /* XXX: Report error someday... */ + continue; + } } } - rcu_read_unlock(); return ret; } @@ -5101,70 +5126,72 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess, * tracer also. */ - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - /* For all registered applications */ - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - ua_sess = lookup_session_by_app(usess, app); - if (!ua_sess) { - /* The application has problem or is probably dead. */ - continue; - } + /* For all registered applications */ + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; + } + ua_sess = lookup_session_by_app(usess, app); + if (!ua_sess) { + /* The application has problem or is probably dead. */ + continue; + } - pthread_mutex_lock(&ua_sess->lock); + pthread_mutex_lock(&ua_sess->lock); - if (ua_sess->deleted) { - pthread_mutex_unlock(&ua_sess->lock); - continue; - } + 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); - /* - * It is possible that the channel cannot be found is - * the channel/event creation occurs concurrently with - * an application exit. - */ - if (!ua_chan_node) { - 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); + /* + * It is possible that the channel cannot be found is + * the channel/event creation occurs concurrently with + * an application exit. + */ + if (!ua_chan_node) { + pthread_mutex_unlock(&ua_sess->lock); + continue; + } - ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node); + ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node); + + /* Get event node */ + ua_event = find_ust_app_event( + ua_chan->events, + uevent->attr.name, + uevent->filter, + (enum lttng_ust_abi_loglevel_type) uevent->attr.loglevel_type, + uevent->attr.loglevel, + uevent->exclusion); + if (ua_event == nullptr) { + DBG3("UST app enable event %s not found for app PID %d." + "Skipping app", + uevent->attr.name, + app->pid); + goto next_app; + } - /* Get event node */ - ua_event = find_ust_app_event(ua_chan->events, - uevent->attr.name, - uevent->filter, - uevent->attr.loglevel, - uevent->exclusion); - if (ua_event == nullptr) { - DBG3("UST app enable event %s not found for app PID %d." - "Skipping app", - uevent->attr.name, - app->pid); - goto next_app; - } - - ret = enable_ust_app_event(ua_event, app); - if (ret < 0) { + ret = enable_ust_app_event(ua_event, app); + if (ret < 0) { + pthread_mutex_unlock(&ua_sess->lock); + goto error; + } + next_app: pthread_mutex_unlock(&ua_sess->lock); - goto error; } - next_app: - pthread_mutex_unlock(&ua_sess->lock); } - error: - rcu_read_unlock(); return ret; } @@ -5188,53 +5215,56 @@ int ust_app_create_event_glb(struct ltt_ust_session *usess, uevent->attr.name, usess->id); - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - /* For all registered applications */ - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - ua_sess = lookup_session_by_app(usess, app); - if (!ua_sess) { - /* The application has problem or is probably dead. */ - continue; - } + /* For all registered applications */ + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; + } - pthread_mutex_lock(&ua_sess->lock); + ua_sess = lookup_session_by_app(usess, app); + if (!ua_sess) { + /* The application has problem or is probably dead. */ + continue; + } - if (ua_sess->deleted) { - pthread_mutex_unlock(&ua_sess->lock); - continue; - } + pthread_mutex_lock(&ua_sess->lock); - /* 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); - /* If the channel is not found, there is a code flow error */ - LTTNG_ASSERT(ua_chan_node); + if (ua_sess->deleted) { + pthread_mutex_unlock(&ua_sess->lock); + continue; + } - ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node); + /* 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); + /* If the channel is not found, there is a code flow error */ + LTTNG_ASSERT(ua_chan_node); - ret = create_ust_app_event(ua_chan, uevent, app); - pthread_mutex_unlock(&ua_sess->lock); - if (ret < 0) { - if (ret != -LTTNG_UST_ERR_EXIST) { - /* Possible value at this point: -ENOMEM. If so, we stop! */ - break; + ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node); + + ret = create_ust_app_event(ua_chan, uevent, app); + pthread_mutex_unlock(&ua_sess->lock); + if (ret < 0) { + if (ret != -LTTNG_UST_ERR_EXIST) { + /* Possible value at this point: -ENOMEM. If so, we stop! */ + break; + } + + DBG2("UST app event %s already exist on app PID %d", + uevent->attr.name, + app->pid); + continue; } - DBG2("UST app event %s already exist on app PID %d", - uevent->attr.name, - app->pid); - continue; } } - rcu_read_unlock(); return ret; } @@ -5251,7 +5281,7 @@ static int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *ap DBG("Starting tracing for ust app pid %d", app->pid); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; if (!app->compatible) { goto end; @@ -5340,13 +5370,11 @@ skip_setup: } end: - rcu_read_unlock(); health_code_update(); return 0; error_unlock: pthread_mutex_unlock(&ua_sess->lock); - rcu_read_unlock(); health_code_update(); return -1; } @@ -5361,7 +5389,7 @@ static int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app DBG("Stopping tracing for ust app pid %d", app->pid); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; if (!app->compatible) { goto end_no_session; @@ -5455,47 +5483,46 @@ static int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app end_unlock: pthread_mutex_unlock(&ua_sess->lock); end_no_session: - rcu_read_unlock(); health_code_update(); return 0; error_rcu_unlock: pthread_mutex_unlock(&ua_sess->lock); - rcu_read_unlock(); health_code_update(); return -1; } -static int ust_app_flush_app_session(struct ust_app *app, struct ust_app_session *ua_sess) +static int ust_app_flush_app_session(ust_app& app, ust_app_session& ua_sess) { int ret, retval = 0; struct lttng_ht_iter iter; struct ust_app_channel *ua_chan; struct consumer_socket *socket; - DBG("Flushing app session buffers for ust app pid %d", app->pid); - - rcu_read_lock(); + DBG("Flushing app session buffers for ust app pid %d", app.pid); - if (!app->compatible) { + if (!app.compatible) { goto end_not_compatible; } - pthread_mutex_lock(&ua_sess->lock); + pthread_mutex_lock(&ua_sess.lock); - if (ua_sess->deleted) { + if (ua_sess.deleted) { goto end_deleted; } health_code_update(); /* Flushing buffers */ - socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, ua_sess->consumer); + socket = consumer_find_socket_by_bitness(app.abi.bits_per_long, ua_sess.consumer); /* Flush buffers and push metadata. */ - switch (ua_sess->buffer_type) { + 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) { + { + lttng::urcu::read_lock_guard read_lock; + + cds_lfht_for_each_entry (ua_sess.channels->ht, &iter.iter, ua_chan, node.node) { health_code_update(); ret = consumer_flush_channel(socket, ua_chan->key); if (ret) { @@ -5504,7 +5531,9 @@ static int ust_app_flush_app_session(struct ust_app *app, struct ust_app_session continue; } } + break; + } case LTTNG_BUFFER_PER_UID: default: abort(); @@ -5514,10 +5543,9 @@ static int ust_app_flush_app_session(struct ust_app *app, struct ust_app_session health_code_update(); end_deleted: - pthread_mutex_unlock(&ua_sess->lock); + pthread_mutex_unlock(&ua_sess.lock); end_not_compatible: - rcu_read_unlock(); health_code_update(); return retval; } @@ -5533,8 +5561,6 @@ static int ust_app_flush_session(struct ltt_ust_session *usess) DBG("Flushing session buffers for all ust apps"); - rcu_read_lock(); - /* Flush buffers and push metadata. */ switch (usess->buffer_type) { case LTTNG_BUFFER_PER_UID: @@ -5544,6 +5570,7 @@ static int ust_app_flush_session(struct ltt_ust_session *usess) /* Flush all per UID buffers associated to that session. */ cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) { + lttng::urcu::read_lock_guard read_lock; lsu::registry_session *ust_session_reg; struct buffer_reg_channel *buf_reg_chan; struct consumer_socket *socket; @@ -5571,6 +5598,7 @@ static int ust_app_flush_session(struct ltt_ust_session *usess) auto locked_registry = ust_session_reg->lock(); (void) push_metadata(locked_registry, usess->consumer); } + break; } case LTTNG_BUFFER_PER_PID: @@ -5578,14 +5606,17 @@ static int ust_app_flush_session(struct ltt_ust_session *usess) struct ust_app_session *ua_sess; struct lttng_ht_iter iter; struct ust_app *app; + lttng::urcu::read_lock_guard read_lock; 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 == nullptr) { continue; } - (void) ust_app_flush_app_session(app, ua_sess); + + (void) ust_app_flush_app_session(*app, *ua_sess); } + break; } default: @@ -5594,7 +5625,6 @@ static int ust_app_flush_session(struct ltt_ust_session *usess) break; } - rcu_read_unlock(); health_code_update(); return ret; } @@ -5608,7 +5638,7 @@ static int ust_app_clear_quiescent_app_session(struct ust_app *app, struct ust_a DBG("Clearing stream quiescent state for ust app pid %d", app->pid); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; if (!app->compatible) { goto end_not_compatible; @@ -5655,7 +5685,6 @@ end_unlock: pthread_mutex_unlock(&ua_sess->lock); end_not_compatible: - rcu_read_unlock(); health_code_update(); return ret; } @@ -5672,8 +5701,6 @@ static int ust_app_clear_quiescent_session(struct ltt_ust_session *usess) DBG("Clearing stream quiescent state for all ust apps"); - rcu_read_lock(); - switch (usess->buffer_type) { case LTTNG_BUFFER_PER_UID: { @@ -5687,6 +5714,7 @@ static int ust_app_clear_quiescent_session(struct ltt_ust_session *usess) cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) { struct consumer_socket *socket; struct buffer_reg_channel *buf_reg_chan; + lttng::urcu::read_lock_guard read_lock; /* Get associated consumer socket.*/ socket = consumer_find_socket_by_bitness(reg->bits_per_long, @@ -5711,6 +5739,7 @@ static int ust_app_clear_quiescent_session(struct ltt_ust_session *usess) buf_reg_chan->consumer_key); } } + break; } case LTTNG_BUFFER_PER_PID: @@ -5718,6 +5747,7 @@ static int ust_app_clear_quiescent_session(struct ltt_ust_session *usess) struct ust_app_session *ua_sess; struct lttng_ht_iter iter; struct ust_app *app; + lttng::urcu::read_lock_guard read_lock; cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { ua_sess = lookup_session_by_app(usess, app); @@ -5726,6 +5756,7 @@ static int ust_app_clear_quiescent_session(struct ltt_ust_session *usess) } (void) ust_app_clear_quiescent_app_session(app, ua_sess); } + break; } default: @@ -5734,7 +5765,6 @@ static int ust_app_clear_quiescent_session(struct ltt_ust_session *usess) break; } - rcu_read_unlock(); health_code_update(); return ret; } @@ -5751,7 +5781,7 @@ static int destroy_trace(struct ltt_ust_session *usess, struct ust_app *app) DBG("Destroy tracing for ust app pid %d", app->pid); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; if (!app->compatible) { goto end; @@ -5791,7 +5821,6 @@ static int destroy_trace(struct ltt_ust_session *usess, struct ust_app *app) } } end: - rcu_read_unlock(); health_code_update(); return 0; } @@ -5812,8 +5841,6 @@ int ust_app_start_trace_all(struct ltt_ust_session *usess) */ usess->active = true; - rcu_read_lock(); - /* * In a start-stop-start use-case, we need to clear the quiescent state * of each channel set by the prior stop command, thus ensuring that a @@ -5822,11 +5849,13 @@ int ust_app_start_trace_all(struct ltt_ust_session *usess) */ (void) ust_app_clear_quiescent_session(usess); - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - ust_app_global_update(usess, app); - } + { + lttng::urcu::read_lock_guard read_lock; - rcu_read_unlock(); + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + ust_app_global_update(usess, app); + } + } return 0; } @@ -5849,20 +5878,20 @@ int ust_app_stop_trace_all(struct ltt_ust_session *usess) */ usess->active = false; - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - ret = ust_app_stop_trace(usess, app); - if (ret < 0) { - /* Continue to next apps even on error */ - continue; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + ret = ust_app_stop_trace(usess, app); + if (ret < 0) { + /* Continue to next apps even on error */ + continue; + } } } (void) ust_app_flush_session(usess); - rcu_read_unlock(); - return 0; } @@ -5877,18 +5906,18 @@ int ust_app_destroy_trace_all(struct ltt_ust_session *usess) DBG("Destroy all UST traces"); - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - ret = destroy_trace(usess, app); - if (ret < 0) { - /* Continue to next apps even on error */ - continue; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + ret = destroy_trace(usess, app); + if (ret < 0) { + /* Continue to next apps even on error */ + continue; + } } } - rcu_read_unlock(); - return 0; } @@ -5928,6 +5957,7 @@ static int ust_app_channel_synchronize_event(struct ust_app_channel *ua_chan, ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name, uevent->filter, + (enum lttng_ust_abi_loglevel_type) uevent->attr.loglevel_type, uevent->attr.loglevel, uevent->exclusion); if (!ua_event) { @@ -5995,8 +6025,8 @@ static void ust_app_synchronize_event_notifier_rules(struct ust_app *app) } for (i = 0; i < count; i++) { - struct lttng_condition *condition; - struct lttng_event_rule *event_rule; + const struct lttng_condition *condition; + const struct lttng_event_rule *event_rule; struct lttng_trigger *trigger; const struct ust_app_event_notifier_rule *looked_up_event_notifier_rule; enum lttng_condition_status condition_status; @@ -6006,7 +6036,7 @@ static void ust_app_synchronize_event_notifier_rules(struct ust_app *app) LTTNG_ASSERT(trigger); token = lttng_trigger_get_tracer_token(trigger); - condition = lttng_trigger_get_condition(trigger); + condition = lttng_trigger_get_const_condition(trigger); if (lttng_condition_get_type(condition) != LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES) { @@ -6014,8 +6044,8 @@ static void ust_app_synchronize_event_notifier_rules(struct ust_app *app) continue; } - condition_status = lttng_condition_event_rule_matches_borrow_rule_mutable( - condition, &event_rule); + condition_status = + lttng_condition_event_rule_matches_get_rule(condition, &event_rule); LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK); if (lttng_event_rule_get_domain_type(event_rule) == LTTNG_DOMAIN_KERNEL) { @@ -6038,54 +6068,55 @@ static void ust_app_synchronize_event_notifier_rules(struct ust_app *app) } } - rcu_read_lock(); - /* Remove all unknown event sources from the app. */ - cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht, - &app_trigger_iter.iter, - event_notifier_rule, - node.node) { - const uint64_t app_token = event_notifier_rule->token; - bool found = false; + { + lttng::urcu::read_lock_guard read_lock; - /* - * Check if the app event trigger still exists on the - * notification side. - */ - for (i = 0; i < count; i++) { - uint64_t notification_thread_token; - const struct lttng_trigger *trigger = - lttng_triggers_get_at_index(triggers, i); + /* Remove all unknown event sources from the app. */ + cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht, + &app_trigger_iter.iter, + event_notifier_rule, + node.node) { + const uint64_t app_token = event_notifier_rule->token; + bool found = false; + + /* + * Check if the app event trigger still exists on the + * notification side. + */ + for (i = 0; i < count; i++) { + uint64_t notification_thread_token; + const struct lttng_trigger *trigger = + lttng_triggers_get_at_index(triggers, i); - LTTNG_ASSERT(trigger); + LTTNG_ASSERT(trigger); - notification_thread_token = lttng_trigger_get_tracer_token(trigger); + notification_thread_token = lttng_trigger_get_tracer_token(trigger); - if (notification_thread_token == app_token) { - found = true; - break; + if (notification_thread_token == app_token) { + found = true; + break; + } } - } - if (found) { - /* Still valid. */ - continue; - } + if (found) { + /* Still valid. */ + continue; + } - /* - * This trigger was unregistered, disable it on the tracer's - * side. - */ - ret = lttng_ht_del(app->token_to_event_notifier_rule_ht, &app_trigger_iter); - LTTNG_ASSERT(ret == 0); + /* + * This trigger was unregistered, disable it on the tracer's + * side. + */ + ret = lttng_ht_del(app->token_to_event_notifier_rule_ht, &app_trigger_iter); + LTTNG_ASSERT(ret == 0); - /* Callee logs errors. */ - (void) disable_ust_object(app, event_notifier_rule->obj); + /* Callee logs errors. */ + (void) disable_ust_object(app, event_notifier_rule->obj); - delete_ust_app_event_notifier_rule(app->sock, event_notifier_rule, app); + delete_ust_app_event_notifier_rule(app->sock, event_notifier_rule, app); + } } - rcu_read_unlock(); - end: lttng_triggers_destroy(triggers); return; @@ -6167,11 +6198,9 @@ static void ust_app_synchronize(struct ltt_ust_session *usess, struct ust_app *a ret = find_or_create_ust_app_session(usess, app, &ua_sess, nullptr); if (ret < 0) { /* Tracer is probably gone or ENOMEM. */ - if (ua_sess) { - destroy_app_session(app, ua_sess); - } goto end; } + LTTNG_ASSERT(ua_sess); pthread_mutex_lock(&ua_sess->lock); @@ -6179,28 +6208,28 @@ static void ust_app_synchronize(struct ltt_ust_session *usess, struct ust_app *a goto deleted_session; } - rcu_read_lock(); + { + lttng::urcu::read_lock_guard read_lock; - ust_app_synchronize_all_channels(usess, ua_sess, app); + ust_app_synchronize_all_channels(usess, ua_sess, app); - /* - * Create the metadata for the application. This returns gracefully if a - * metadata was already set for the session. - * - * The metadata channel must be created after the data channels as the - * consumer daemon assumes this ordering. When interacting with a relay - * daemon, the consumer will use this assumption to send the - * "STREAMS_SENT" message to the relay daemon. - */ - ret = create_ust_app_metadata(ua_sess, app, usess->consumer); - if (ret < 0) { - ERR("Metadata creation failed for app sock %d for session id %" PRIu64, - app->sock, - usess->id); + /* + * Create the metadata for the application. This returns gracefully if a + * metadata was already set for the session. + * + * The metadata channel must be created after the data channels as the + * consumer daemon assumes this ordering. When interacting with a relay + * daemon, the consumer will use this assumption to send the + * "STREAMS_SENT" message to the relay daemon. + */ + ret = create_ust_app_metadata(ua_sess, app, usess->consumer); + if (ret < 0) { + ERR("Metadata creation failed for app sock %d for session id %" PRIu64, + app->sock, + usess->id); + } } - rcu_read_unlock(); - deleted_session: pthread_mutex_unlock(&ua_sess->lock); end: @@ -6285,11 +6314,13 @@ 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); + { + lttng::urcu::read_lock_guard 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(); } void ust_app_global_update_all_event_notifier_rules() @@ -6297,12 +6328,10 @@ void ust_app_global_update_all_event_notifier_rules() struct lttng_ht_iter iter; struct ust_app *app; - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { ust_app_global_update_event_notifier_rules(app); } - - rcu_read_unlock(); } /* @@ -6321,43 +6350,44 @@ int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess, LTTNG_ASSERT(usess->active); - rcu_read_lock(); - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - ua_sess = lookup_session_by_app(usess, app); - if (ua_sess == nullptr) { - continue; - } + { + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; + } + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == nullptr) { + continue; + } - pthread_mutex_lock(&ua_sess->lock); + pthread_mutex_lock(&ua_sess->lock); - if (ua_sess->deleted) { - pthread_mutex_unlock(&ua_sess->lock); - continue; - } + 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); - if (ua_chan_node == nullptr) { - goto next_app; - } - ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - ret = create_ust_app_channel_context(ua_chan, &uctx->ctx, app); - if (ret < 0) { - goto next_app; + /* 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); + if (ua_chan_node == nullptr) { + goto next_app; + } + ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); + ret = create_ust_app_channel_context(ua_chan, &uctx->ctx, app); + if (ret < 0) { + goto next_app; + } + next_app: + pthread_mutex_unlock(&ua_sess->lock); } - next_app: - pthread_mutex_unlock(&ua_sess->lock); } - rcu_read_unlock(); return ret; } @@ -6492,7 +6522,8 @@ static int handle_app_register_channel_notification(int sock, struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; auto ust_ctl_context_fields = - lttng::make_unique_wrapper(raw_context_fields); + lttng::make_unique_wrapper( + raw_context_fields); lttng::urcu::read_lock_guard read_lock_guard; @@ -6586,7 +6617,7 @@ static int handle_app_register_channel_notification(int sock, goto reply; } } - } catch (std::exception& ex) { + } catch (const std::exception& ex) { ERR("Failed to handle application context: %s", ex.what()); ret_code = -EINVAL; goto reply; @@ -6656,9 +6687,11 @@ static int add_event_ust_registry(int sock, struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; lttng::urcu::read_lock_guard rcu_lock; - auto signature = lttng::make_unique_wrapper(raw_signature); - auto fields = lttng::make_unique_wrapper(raw_fields); - auto model_emf_uri = lttng::make_unique_wrapper(raw_model_emf_uri); + auto signature = lttng::make_unique_wrapper(raw_signature); + auto fields = + lttng::make_unique_wrapper(raw_fields); + auto model_emf_uri = + lttng::make_unique_wrapper(raw_model_emf_uri); /* Lookup application. If not found, there is a code flow error. */ app = find_app_by_notify_sock(sock); @@ -6779,8 +6812,9 @@ static int add_enum_ust_registry(int sock, struct ust_app_session *ua_sess; uint64_t enum_id = -1ULL; lttng::urcu::read_lock_guard read_lock_guard; - auto entries = lttng::make_unique_wrapper( - raw_entries); + auto entries = + lttng::make_unique_wrapper( + raw_entries); /* Lookup application. If not found, there is a code flow error. */ app = find_app_by_notify_sock(sock); @@ -6816,7 +6850,7 @@ static int add_enum_ust_registry(int sock, application_reply_code = 0; } catch (const std::exception& ex) { ERR("%s: %s", - fmt::format( + lttng::format( "Failed to create or find enumeration provided by application: app = {}, enumeration name = {}", *app, name) @@ -7049,7 +7083,7 @@ void ust_app_notify_sock_unregister(int sock) LTTNG_ASSERT(sock >= 0); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; obj = zmalloc(); if (!obj) { @@ -7096,7 +7130,6 @@ void ust_app_notify_sock_unregister(int sock) (void) lttng_ht_del(ust_app_ht_by_notify_sock, &iter); close_socket: - rcu_read_unlock(); /* * Close socket after a grace period to avoid for the socket to be reused @@ -7111,13 +7144,9 @@ close_socket: /* * Destroy a ust app data structure and free its memory. */ -void ust_app_destroy(struct ust_app *app) +static void ust_app_destroy(ust_app& app) { - if (!app) { - return; - } - - call_rcu(&app->pid_n.head, delete_ust_app_rcu); + call_rcu(&app.pid_n.head, delete_ust_app_rcu); } /* @@ -7139,13 +7168,13 @@ enum lttng_error_code ust_app_snapshot_record(const struct ltt_ust_session *uses LTTNG_ASSERT(usess); LTTNG_ASSERT(output); - rcu_read_lock(); - switch (usess->buffer_type) { case LTTNG_BUFFER_PER_UID: { struct buffer_reg_uid *reg; + lttng::urcu::read_lock_guard read_lock; + cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) { struct buffer_reg_channel *buf_reg_chan; struct consumer_socket *socket; @@ -7208,10 +7237,13 @@ enum lttng_error_code ust_app_snapshot_record(const struct ltt_ust_session *uses goto error; } } + break; } case LTTNG_BUFFER_PER_PID: { + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { struct consumer_socket *socket; struct lttng_ht_iter chan_iter; @@ -7298,7 +7330,6 @@ enum lttng_error_code ust_app_snapshot_record(const struct ltt_ust_session *uses error: free(trace_path); - rcu_read_unlock(); return status; } @@ -7322,7 +7353,8 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(const struct ltt_ust_sessio cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) { struct buffer_reg_channel *buf_reg_chan; - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry ( reg->registry->channels->ht, &iter.iter, buf_reg_chan, node.node) { if (cur_nr_packets >= buf_reg_chan->num_subbuf) { @@ -7334,13 +7366,13 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(const struct ltt_ust_sessio } tot_size += buf_reg_chan->subbuf_size * buf_reg_chan->stream_count; } - rcu_read_unlock(); } break; } case LTTNG_BUFFER_PER_PID: { - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; @@ -7364,7 +7396,6 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(const struct ltt_ust_sessio tot_size += ua_chan->attr.subbuf_size * ua_chan->streams.count; } } - rcu_read_unlock(); break; } default: @@ -7425,11 +7456,12 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess, *discarded = 0; *lost = 0; - rcu_read_lock(); /* * Iterate over every registered applications. Sum counters for * all applications containing requested session and channel. */ + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { struct lttng_ht_iter uiter; @@ -7466,7 +7498,6 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess, } } - rcu_read_unlock(); return ret; } @@ -7477,7 +7508,7 @@ static int ust_app_regenerate_statedump(struct ltt_ust_session *usess, struct us DBG("Regenerating the metadata for ust app pid %d", app->pid); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; ua_sess = lookup_session_by_app(usess, app); if (ua_sess == nullptr) { @@ -7499,7 +7530,6 @@ end_unlock: pthread_mutex_unlock(&ua_sess->lock); end: - rcu_read_unlock(); health_code_update(); return ret; } @@ -7515,7 +7545,7 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess) DBG("Regenerating the metadata for all UST apps"); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { if (!app->compatible) { @@ -7529,8 +7559,6 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess) } } - rcu_read_unlock(); - return 0; } @@ -7544,13 +7572,10 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) int ret; enum lttng_error_code cmd_ret = LTTNG_OK; struct lttng_ht_iter iter; - struct ust_app *app; struct ltt_ust_session *usess = session->ust_session; LTTNG_ASSERT(usess); - rcu_read_lock(); - switch (usess->buffer_type) { case LTTNG_BUFFER_PER_UID: { @@ -7559,6 +7584,7 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) { struct buffer_reg_channel *buf_reg_chan; struct consumer_socket *socket; + lttng::urcu::read_lock_guard read_lock; /* Get consumer socket to use to push the metadata.*/ socket = consumer_find_socket_by_bitness(reg->bits_per_long, @@ -7612,14 +7638,28 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) } case LTTNG_BUFFER_PER_PID: { - cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { + lttng::urcu::read_lock_guard read_lock; + ust_app *raw_app; + + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, raw_app, pid_n.node) { struct consumer_socket *socket; struct lttng_ht_iter chan_iter; struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; lsu::registry_session *registry; + bool app_reference_taken; - ua_sess = lookup_session_by_app(usess, app); + app_reference_taken = ust_app_get(*raw_app); + if (!app_reference_taken) { + /* Application unregistered concurrently, skip it. */ + DBG("Could not get application reference as it is being torn down; skipping application"); + continue; + } + + ust_app_reference app(raw_app); + raw_app = nullptr; + + ua_sess = lookup_session_by_app(usess, app.get()); if (!ua_sess) { /* Session not associated with this app. */ continue; @@ -7634,10 +7674,7 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) } registry = get_session_registry(ua_sess); - if (!registry) { - DBG("Application session is being torn down. Skip application."); - continue; - } + LTTNG_ASSERT(registry); /* Rotate the data channels. */ cds_lfht_for_each_entry ( @@ -7647,9 +7684,6 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) ua_sess->consumer, /* is_metadata_channel */ false); if (ret < 0) { - /* Per-PID buffer and application going away. */ - if (ret == -LTTNG_ERR_CHAN_NOT_FOUND) - continue; cmd_ret = LTTNG_ERR_ROTATION_FAIL_CONSUMER; goto error; } @@ -7661,18 +7695,17 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) (void) push_metadata(locked_registry, usess->consumer); } + ret = consumer_rotate_channel(socket, registry->_metadata_key, ua_sess->consumer, /* is_metadata_channel */ true); if (ret < 0) { - /* Per-PID buffer and application going away. */ - if (ret == -LTTNG_ERR_CHAN_NOT_FOUND) - continue; cmd_ret = LTTNG_ERR_ROTATION_FAIL_CONSUMER; goto error; } } + break; } default: @@ -7683,7 +7716,6 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) cmd_ret = LTTNG_OK; error: - rcu_read_unlock(); return cmd_ret; } @@ -7696,12 +7728,12 @@ enum lttng_error_code ust_app_create_channel_subdirectories(const struct ltt_ust int fmt_ret; LTTNG_ASSERT(usess->current_trace_chunk); - rcu_read_lock(); switch (usess->buffer_type) { case LTTNG_BUFFER_PER_UID: { struct buffer_reg_uid *reg; + lttng::urcu::read_lock_guard read_lock; cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) { fmt_ret = asprintf(&pathname_index, @@ -7732,6 +7764,7 @@ enum lttng_error_code ust_app_create_channel_subdirectories(const struct ltt_ust case LTTNG_BUFFER_PER_PID: { struct ust_app *app; + lttng::urcu::read_lock_guard read_lock; /* * Create the toplevel ust/ directory in case no apps are running. @@ -7787,7 +7820,6 @@ enum lttng_error_code ust_app_create_channel_subdirectories(const struct ltt_ust ret = LTTNG_OK; error: - rcu_read_unlock(); return ret; } @@ -7806,8 +7838,6 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session) LTTNG_ASSERT(usess); - rcu_read_lock(); - if (usess->active) { ERR("Expecting inactive session %s (%" PRIu64 ")", session->name, session->id); cmd_ret = LTTNG_ERR_FATAL; @@ -7818,6 +7848,7 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session) case LTTNG_BUFFER_PER_UID: { struct buffer_reg_uid *reg; + lttng::urcu::read_lock_guard read_lock; cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) { struct buffer_reg_channel *buf_reg_chan; @@ -7859,6 +7890,8 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session) } case LTTNG_BUFFER_PER_PID: { + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { struct consumer_socket *socket; struct lttng_ht_iter chan_iter; @@ -7939,7 +7972,6 @@ error: error_socket: end: - rcu_read_unlock(); return cmd_ret; } @@ -7967,8 +7999,6 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session) LTTNG_ASSERT(usess); - rcu_read_lock(); - switch (usess->buffer_type) { case LTTNG_BUFFER_PER_UID: { @@ -7977,6 +8007,7 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session) cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) { struct buffer_reg_channel *buf_reg_chan; struct consumer_socket *socket; + lttng::urcu::read_lock_guard read_lock; socket = consumer_find_socket_by_bitness(reg->bits_per_long, usess->consumer); @@ -8001,6 +8032,7 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session) case LTTNG_BUFFER_PER_PID: { struct ust_app *app; + lttng::urcu::read_lock_guard read_lock; cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) { struct consumer_socket *socket; @@ -8056,7 +8088,6 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session) } error: - rcu_read_unlock(); return ret; } @@ -8085,4 +8116,26 @@ lsu::ctl_field_quirks ust_app::ctl_field_quirks() const */ return v_major <= 9 ? lsu::ctl_field_quirks::UNDERSCORE_PREFIXED_VARIANT_TAG_MAPPINGS : lsu::ctl_field_quirks::NONE; -} \ No newline at end of file +} + +static void ust_app_release(urcu_ref *ref) +{ + auto& app = *lttng::utils::container_of(ref, &ust_app::ref); + + ust_app_unregister(app); + ust_app_destroy(app); +} + +bool ust_app_get(ust_app& app) +{ + return urcu_ref_get_unless_zero(&app.ref); +} + +void ust_app_put(struct ust_app *app) +{ + if (!app) { + return; + } + + urcu_ref_put(&app->ref, ust_app_release); +}