X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fsession.cpp;h=1846024fcc60670d505a740db81125c7ec1e0aec;hb=e99e366487cb113a1041e4217ba181feb52d05c9;hp=0d19042b594f8edfda6817a866cf6931378a8b4b;hpb=7966af5763c4aaca39df9bbfa9277ff15715c720;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/session.cpp b/src/bin/lttng-sessiond/session.cpp index 0d19042b5..1846024fc 100644 --- a/src/bin/lttng-sessiond/session.cpp +++ b/src/bin/lttng-sessiond/session.cpp @@ -1,36 +1,39 @@ /* - * Copyright (C) 2011 David Goulet + * Copyright (C) 2011 EfficiOS Inc. * * SPDX-License-Identifier: GPL-2.0-only * */ #define _LGPL_SOURCE -#include +#include #include +#include +#include #include #include #include #include -#include -#include #include -#include +#include -#include -#include -#include -#include -#include -#include "lttng-sessiond.h" -#include "kernel.h" +#include +#include +#include +#include +#include -#include "session.h" -#include "utils.h" -#include "trace-ust.h" -#include "timer.h" -#include "cmd.h" +#include "lttng-sessiond.hpp" +#include +#include "cmd.hpp" +#include "kernel.hpp" +#include "session.hpp" +#include "timer.hpp" +#include "trace-ust.hpp" +#include "utils.hpp" + +namespace { struct ltt_session_destroy_notifier_element { ltt_session_destroy_notifier notifier; void *user_data; @@ -41,6 +44,8 @@ struct ltt_session_clear_notifier_element { void *user_data; }; +namespace ls = lttng::sessiond; + /* * NOTES: * @@ -50,25 +55,26 @@ struct ltt_session_clear_notifier_element { * using session_lock() and session_unlock(). */ +/* These characters are forbidden in a session name. Used by validate_name. */ +const char *forbidden_name_chars = "/"; + +/* Global hash table to keep the sessions, indexed by id. */ +struct lttng_ht *ltt_sessions_ht_by_id = NULL; +/* Global hash table to keep the sessions, indexed by name. */ +struct lttng_ht *ltt_sessions_ht_by_name = NULL; + /* * Init tracing session list. * * Please see session.h for more explanation and correct usage of the list. */ -static struct ltt_session_list ltt_session_list = { +struct ltt_session_list the_session_list = { .lock = PTHREAD_MUTEX_INITIALIZER, .removal_cond = PTHREAD_COND_INITIALIZER, .next_uuid = 0, - .head = CDS_LIST_HEAD_INIT(ltt_session_list.head), + .head = CDS_LIST_HEAD_INIT(the_session_list.head), }; - -/* These characters are forbidden in a session name. Used by validate_name. */ -static const char *forbidden_name_chars = "/"; - -/* Global hash table to keep the sessions, indexed by id. */ -static struct lttng_ht *ltt_sessions_ht_by_id = NULL; -/* Global hash table to keep the sessions, indexed by name. */ -static struct lttng_ht *ltt_sessions_ht_by_name = NULL; +} /* namespace */ /* * Validate the session name for forbidden characters. @@ -113,8 +119,8 @@ static uint64_t add_session_list(struct ltt_session *ls) { LTTNG_ASSERT(ls); - cds_list_add(&ls->list, <t_session_list.head); - return ltt_session_list.next_uuid++; + cds_list_add(&ls->list, &the_session_list.head); + return the_session_list.next_uuid++; } /* @@ -134,7 +140,7 @@ static void del_session_list(struct ltt_session *ls) */ struct ltt_session_list *session_get_list(void) { - return <t_session_list; + return &the_session_list; } /* @@ -142,12 +148,12 @@ struct ltt_session_list *session_get_list(void) */ void session_list_wait_empty(void) { - pthread_mutex_lock(<t_session_list.lock); - while (!cds_list_empty(<t_session_list.head)) { - pthread_cond_wait(<t_session_list.removal_cond, - <t_session_list.lock); + pthread_mutex_lock(&the_session_list.lock); + while (!cds_list_empty(&the_session_list.head)) { + pthread_cond_wait(&the_session_list.removal_cond, + &the_session_list.lock); } - pthread_mutex_unlock(<t_session_list.lock); + pthread_mutex_unlock(&the_session_list.lock); } /* @@ -155,7 +161,7 @@ void session_list_wait_empty(void) */ void session_lock_list(void) { - pthread_mutex_lock(<t_session_list.lock); + pthread_mutex_lock(&the_session_list.lock); } /* @@ -163,7 +169,7 @@ void session_lock_list(void) */ int session_trylock_list(void) { - return pthread_mutex_trylock(<t_session_list.lock); + return pthread_mutex_trylock(&the_session_list.lock); } /* @@ -171,7 +177,7 @@ int session_trylock_list(void) */ void session_unlock_list(void) { - pthread_mutex_unlock(<t_session_list.lock); + pthread_mutex_unlock(&the_session_list.lock); } /* @@ -331,12 +337,12 @@ end: static void ltt_sessions_ht_destroy(void) { if (ltt_sessions_ht_by_id) { - ht_cleanup_push(ltt_sessions_ht_by_id); + lttng_ht_destroy(ltt_sessions_ht_by_id); ltt_sessions_ht_by_id = NULL; } if (ltt_sessions_ht_by_name) { - ht_cleanup_push(ltt_sessions_ht_by_name); + lttng_ht_destroy(ltt_sessions_ht_by_name); ltt_sessions_ht_by_name = NULL; } @@ -377,28 +383,49 @@ end: /* * Test if ltt_sessions_ht_by_id/name are empty. - * Return 1 if empty, 0 if not empty. + * Return `false` if hash table objects are null. * The session list lock must be held. */ -static int ltt_sessions_ht_empty(void) +static bool ltt_sessions_ht_empty(void) { - unsigned long count; + bool empty = false; if (!ltt_sessions_ht_by_id) { - count = 0; + /* The hash tables do not exist yet. */ goto end; } LTTNG_ASSERT(ltt_sessions_ht_by_name); - count = lttng_ht_get_count(ltt_sessions_ht_by_id); - LTTNG_ASSERT(count == lttng_ht_get_count(ltt_sessions_ht_by_name)); + if (lttng_ht_get_count(ltt_sessions_ht_by_id) != 0) { + /* Not empty.*/ + goto end; + } + + /* + * At this point it is expected that the `ltt_sessions_ht_by_name` ht is + * empty. + * + * The removal from both hash tables is done in two different + * places: + * - removal from `ltt_sessions_ht_by_name` is done during + * `session_destroy()` + * - removal from `ltt_sessions_ht_by_id` is done later + * in `session_release()` on the last reference put. + * + * This means that it is possible for `ltt_sessions_ht_by_name` to be + * empty but for `ltt_sessions_ht_by_id` to still contain objects when + * multiple sessions exists. The reverse is false, hence this sanity + * check. + */ + LTTNG_ASSERT(lttng_ht_get_count(ltt_sessions_ht_by_name) == 0); + empty = true; end: - return count ? 0 : 1; + return empty; } /* - * Remove a ltt_session from the ltt_sessions_ht_by_id/name. + * Remove a ltt_session from the ltt_sessions_ht_by_id. * If empty, the ltt_sessions_ht_by_id/name HTs are freed. * The session list lock must be held. */ @@ -415,10 +442,6 @@ static void del_session_ht(struct ltt_session *ls) ret = lttng_ht_del(ltt_sessions_ht_by_id, &iter); LTTNG_ASSERT(!ret); - iter.iter.node = &ls->node_by_name.node; - ret = lttng_ht_del(ltt_sessions_ht_by_name, &iter); - LTTNG_ASSERT(!ret); - if (ltt_sessions_ht_empty()) { DBG("Empty ltt_sessions_ht_by_id/name, destroying hast tables"); ltt_sessions_ht_destroy(); @@ -998,7 +1021,7 @@ void session_release(struct urcu_ref *ref) pthread_mutex_destroy(&session->lock); if (session_published) { - ASSERT_LOCKED(ltt_session_list.lock); + ASSERT_LOCKED(the_session_list.lock); del_session_list(session); del_session_ht(session); } @@ -1015,14 +1038,15 @@ void session_release(struct urcu_ref *ref) lttng_dynamic_array_reset(&session->clear_notifiers); free(session->last_archived_chunk_name); free(session->base_path); + lttng_trigger_put(session->rotate_trigger); free(session); if (session_published) { /* * Broadcast after free-ing to ensure the memory is * reclaimed before the main thread exits. */ - ASSERT_LOCKED(ltt_session_list.lock); - pthread_cond_broadcast(<t_session_list.removal_cond); + ASSERT_LOCKED(the_session_list.lock); + pthread_cond_broadcast(&the_session_list.removal_cond); } } @@ -1047,7 +1071,7 @@ void session_put(struct ltt_session *session) * The session list lock must be held as any session_put() * may cause the removal of the session from the session_list. */ - ASSERT_LOCKED(ltt_session_list.lock); + ASSERT_LOCKED(the_session_list.lock); LTTNG_ASSERT(session->ref.refcount); urcu_ref_put(&session->ref, session_release); } @@ -1065,8 +1089,23 @@ void session_put(struct ltt_session *session) */ void session_destroy(struct ltt_session *session) { + int ret; + struct lttng_ht_iter iter; + LTTNG_ASSERT(!session->destroyed); session->destroyed = true; + + /* + * Remove immediately from the "session by name" hash table. Only one + * session is expected to exist with a given name for at any given time. + * + * Even if a session still technically exists for a little while longer, + * there is no point in performing action on a "destroyed" session. + */ + iter.iter.node = &session->node_by_name.node; + ret = lttng_ht_del(ltt_sessions_ht_by_name, &iter); + LTTNG_ASSERT(!ret); + session_put(session); } @@ -1105,11 +1144,11 @@ struct ltt_session *session_find_by_name(const char *name) struct ltt_session *iter; LTTNG_ASSERT(name); - ASSERT_LOCKED(ltt_session_list.lock); + ASSERT_LOCKED(the_session_list.lock); DBG2("Trying to find session by name %s", name); - cds_list_for_each_entry(iter, <t_session_list.head, list) { + cds_list_for_each_entry(iter, &the_session_list.head, list) { if (!strncmp(iter->name, name, NAME_MAX) && !iter->destroyed) { goto found; @@ -1132,7 +1171,8 @@ struct ltt_session *session_find_by_id(uint64_t id) struct lttng_ht_iter iter; struct ltt_session *ls; - ASSERT_LOCKED(ltt_session_list.lock); + ASSERT_RCU_READ_LOCKED(); + ASSERT_LOCKED(the_session_list.lock); if (!ltt_sessions_ht_by_id) { goto end; @@ -1164,7 +1204,7 @@ enum lttng_error_code session_create(const char *name, uid_t uid, gid_t gid, enum lttng_error_code ret_code; struct ltt_session *new_session = NULL; - ASSERT_LOCKED(ltt_session_list.lock); + ASSERT_LOCKED(the_session_list.lock); if (name) { struct ltt_session *clashing_session; @@ -1175,7 +1215,7 @@ enum lttng_error_code session_create(const char *name, uid_t uid, gid_t gid, goto error; } } - new_session = (ltt_session *) zmalloc(sizeof(struct ltt_session)); + new_session = zmalloc(); if (!new_session) { PERROR("Failed to allocate an ltt_session structure"); ret_code = LTTNG_ERR_NOMEM; @@ -1358,7 +1398,7 @@ int session_reset_rotation_state(struct ltt_session *session, { int ret = 0; - ASSERT_LOCKED(ltt_session_list.lock); + ASSERT_LOCKED(the_session_list.lock); ASSERT_LOCKED(session->lock); session->rotation_state = result; @@ -1425,3 +1465,38 @@ end: rcu_read_unlock(); return found; } + +void ls::details::locked_session_release(ltt_session *session) +{ + session_unlock(session); + session_put(session); +} + +ltt_session::locked_ptr ls::find_locked_session_by_id(ltt_session::id_t id) +{ + lttng::urcu::read_lock_guard rcu_lock; + auto session = session_find_by_id(id); + + if (!session) { + return nullptr; + } + + /* + * The pointer falling out of scope will unlock and release the reference to the + * session. + */ + session_lock(session); + return ltt_session::locked_ptr(session); +} + +ltt_session::sptr ls::find_session_by_id(ltt_session::id_t id) +{ + lttng::urcu::read_lock_guard rcu_lock; + auto session = session_find_by_id(id); + + if (!session) { + return nullptr; + } + + return {session, session_put}; +}