From a0a4f3143babeaf7779c99e2ec2a8c04c89874d6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Tue, 28 May 2024 03:21:18 +0000 Subject: [PATCH] sessiond: propagate the use of ltt_session::locked_ref MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The mix of managed and unmanaged ltt_session references makes their use potentially confusing. Move to managed locked references for most of the client request processing paths. Change-Id: Iecb1668969ba07acfd84aa25127adb0addddbf10 Signed-off-by: Jérémie Galarneau --- src/bin/lttng-sessiond/Makefile.am | 5 +- src/bin/lttng-sessiond/action-executor.cpp | 314 +++++++++--------- src/bin/lttng-sessiond/clear.cpp | 4 +- src/bin/lttng-sessiond/clear.hpp | 2 +- src/bin/lttng-sessiond/client.cpp | 147 ++++---- src/bin/lttng-sessiond/cmd.cpp | 183 +++++----- src/bin/lttng-sessiond/cmd.hpp | 60 ++-- .../consumer-destination-type.hpp | 16 + src/bin/lttng-sessiond/consumer-output.hpp | 17 + src/bin/lttng-sessiond/consumer.cpp | 3 +- src/bin/lttng-sessiond/consumer.hpp | 11 +- src/bin/lttng-sessiond/dispatch.cpp | 1 - src/bin/lttng-sessiond/kernel-consumer.cpp | 23 +- src/bin/lttng-sessiond/kernel.cpp | 8 +- src/bin/lttng-sessiond/kernel.hpp | 6 +- src/bin/lttng-sessiond/main.cpp | 19 +- src/bin/lttng-sessiond/rotation-thread.cpp | 180 +++++----- src/bin/lttng-sessiond/save.cpp | 104 +++--- src/bin/lttng-sessiond/session.cpp | 103 +++--- src/bin/lttng-sessiond/session.hpp | 184 +++++----- src/bin/lttng-sessiond/snapshot-output.hpp | 28 ++ src/bin/lttng-sessiond/snapshot.cpp | 8 +- src/bin/lttng-sessiond/snapshot.hpp | 18 +- src/bin/lttng-sessiond/timer.cpp | 35 +- src/bin/lttng-sessiond/timer.hpp | 8 +- src/bin/lttng-sessiond/ust-app.cpp | 114 +++---- src/bin/lttng-sessiond/ust-app.hpp | 12 +- src/bin/lttng-sessiond/utils.cpp | 2 +- src/bin/lttng-sessiond/utils.hpp | 5 +- src/bin/lttng/exception.cpp | 5 +- src/bin/lttng/exception.hpp | 5 +- src/common/Makefile.am | 2 + src/common/exception.cpp | 7 +- src/common/make-unique-wrapper.hpp | 16 +- src/common/meta-helpers.hpp | 37 +++ src/common/reference.hpp | 64 ++++ tests/unit/test_session.cpp | 52 +-- 37 files changed, 950 insertions(+), 858 deletions(-) create mode 100644 src/bin/lttng-sessiond/consumer-destination-type.hpp create mode 100644 src/bin/lttng-sessiond/consumer-output.hpp create mode 100644 src/bin/lttng-sessiond/snapshot-output.hpp create mode 100644 src/common/meta-helpers.hpp create mode 100644 src/common/reference.hpp diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am index 15a922710..7dc4bbe4e 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -62,7 +62,10 @@ liblttng_sessiond_common_la_SOURCES = utils.cpp utils.hpp \ clock-class.hpp clock-class.cpp \ event-class.hpp event-class.cpp \ stream-class.hpp stream-class.cpp \ - trace-class.hpp trace-class.cpp + trace-class.hpp trace-class.cpp \ + consumer-destination-type.hpp \ + consumer-output.hpp \ + snapshot-output.hpp if HAVE_LIBLTTNG_UST_CTL liblttng_sessiond_common_la_SOURCES += trace-ust.cpp ust-registry.cpp ust-app.cpp \ diff --git a/src/bin/lttng-sessiond/action-executor.cpp b/src/bin/lttng-sessiond/action-executor.cpp index e3eded0fa..aa8be1fcf 100644 --- a/src/bin/lttng-sessiond/action-executor.cpp +++ b/src/bin/lttng-sessiond/action-executor.cpp @@ -174,7 +174,7 @@ static const char *get_action_name(const struct lttng_action *action) /* Check if this trigger allowed to interect with a given session. */ static bool is_trigger_allowed_for_session(const struct lttng_trigger *trigger, - struct ltt_session *session) + const ltt_session::locked_ref& session) { bool is_allowed = false; const struct lttng_credentials session_creds = { @@ -311,18 +311,51 @@ static int action_executor_start_session_handler(struct action_executor *executo } /* - * Mind the order of the declaration of list_lock vs target_session: + * Mind the order of the declaration of list_lock vs session: * the session list lock must always be released _after_ the release of * a session's reference (the destruction of a ref/locked_ref) to ensure * since the reference's release may unpublish the session from the list of * sessions. */ const auto list_lock = lttng::sessiond::lock_session_list(); - ltt_session::locked_ref session; - try { - session = ltt_session::find_locked_session( + const auto session = ltt_session::find_locked_session( LTTNG_OPTIONAL_GET(item->context.session_id)); + + if (session->destroyed) { + DBG("Session `%s` with id = %" PRIu64 + " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`", + session->name, + session->id, + get_action_name(action), + get_trigger_name(work_item->trigger)); + return 0; + } + + if (!is_trigger_allowed_for_session(work_item->trigger, session)) { + return 0; + } + + cmd_ret = (lttng_error_code) cmd_start_trace(session); + switch (cmd_ret) { + case LTTNG_OK: + DBG("Successfully started session `%s` on behalf of trigger `%s`", + session_name, + get_trigger_name(work_item->trigger)); + break; + case LTTNG_ERR_TRACE_ALREADY_STARTED: + DBG("Attempted to start session `%s` on behalf of trigger `%s` but it was already started", + session_name, + get_trigger_name(work_item->trigger)); + break; + default: + WARN("Failed to start session `%s` on behalf of trigger `%s`: %s", + session_name, + get_trigger_name(work_item->trigger), + lttng_strerror(-cmd_ret)); + lttng_action_increase_execution_failure_count(action); + break; + } } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { DBG_FMT("Failed to execution trigger action: {}, action=`{}`, trigger_name=`{}`, location='{}'", ex.what(), @@ -331,42 +364,6 @@ static int action_executor_start_session_handler(struct action_executor *executo get_trigger_name(work_item->trigger), ex.source_location); lttng_action_increase_execution_failure_count(action); - return 0; - } - - if (session->destroyed) { - DBG("Session `%s` with id = %" PRIu64 - " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`", - session->name, - session->id, - get_action_name(action), - get_trigger_name(work_item->trigger)); - return 0; - } - - if (!is_trigger_allowed_for_session(work_item->trigger, session.get())) { - return 0; - } - - cmd_ret = (lttng_error_code) cmd_start_trace(session.get()); - switch (cmd_ret) { - case LTTNG_OK: - DBG("Successfully started session `%s` on behalf of trigger `%s`", - session_name, - get_trigger_name(work_item->trigger)); - break; - case LTTNG_ERR_TRACE_ALREADY_STARTED: - DBG("Attempted to start session `%s` on behalf of trigger `%s` but it was already started", - session_name, - get_trigger_name(work_item->trigger)); - break; - default: - WARN("Failed to start session `%s` on behalf of trigger `%s`: %s", - session_name, - get_trigger_name(work_item->trigger), - lttng_strerror(-cmd_ret)); - lttng_action_increase_execution_failure_count(action); - break; } return 0; @@ -404,18 +401,52 @@ static int action_executor_stop_session_handler(struct action_executor *executor } /* - * Mind the order of the declaration of list_lock vs target_session: + * Mind the order of the declaration of list_lock vs session: * the session list lock must always be released _after_ the release of * a session's reference (the destruction of a ref/locked_ref) to ensure * since the reference's release may unpublish the session from the list of * sessions. */ const auto list_lock = lttng::sessiond::lock_session_list(); - ltt_session::locked_ref session; try { - session = ltt_session::find_locked_session( + const auto session = ltt_session::find_locked_session( LTTNG_OPTIONAL_GET(item->context.session_id)); + + if (session->destroyed) { + DBG("Session `%s` with id = %" PRIu64 + " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`", + session->name, + session->id, + get_action_name(action), + get_trigger_name(work_item->trigger)); + return 0; + } + + if (!is_trigger_allowed_for_session(work_item->trigger, session)) { + return 0; + } + + cmd_ret = (lttng_error_code) cmd_stop_trace(session); + switch (cmd_ret) { + case LTTNG_OK: + DBG("Successfully stopped session `%s` on behalf of trigger `%s`", + session_name, + get_trigger_name(work_item->trigger)); + break; + case LTTNG_ERR_TRACE_ALREADY_STOPPED: + DBG("Attempted to stop session `%s` on behalf of trigger `%s` but it was already stopped", + session_name, + get_trigger_name(work_item->trigger)); + break; + default: + WARN("Failed to stop session `%s` on behalf of trigger `%s`: %s", + session_name, + get_trigger_name(work_item->trigger), + lttng_strerror(-cmd_ret)); + lttng_action_increase_execution_failure_count(action); + break; + } } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { DBG_FMT("Failed to execution trigger action: {}, action=`{}`, trigger_name=`{}`, location='{}'", ex.what(), @@ -424,42 +455,6 @@ static int action_executor_stop_session_handler(struct action_executor *executor get_trigger_name(work_item->trigger), ex.source_location); lttng_action_increase_execution_failure_count(action); - return 0; - } - - if (session->destroyed) { - DBG("Session `%s` with id = %" PRIu64 - " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`", - session->name, - session->id, - get_action_name(action), - get_trigger_name(work_item->trigger)); - return 0; - } - - if (!is_trigger_allowed_for_session(work_item->trigger, session.get())) { - return 0; - } - - cmd_ret = (lttng_error_code) cmd_stop_trace(session.get()); - switch (cmd_ret) { - case LTTNG_OK: - DBG("Successfully stopped session `%s` on behalf of trigger `%s`", - session_name, - get_trigger_name(work_item->trigger)); - break; - case LTTNG_ERR_TRACE_ALREADY_STOPPED: - DBG("Attempted to stop session `%s` on behalf of trigger `%s` but it was already stopped", - session_name, - get_trigger_name(work_item->trigger)); - break; - default: - WARN("Failed to stop session `%s` on behalf of trigger `%s`: %s", - session_name, - get_trigger_name(work_item->trigger), - lttng_strerror(-cmd_ret)); - lttng_action_increase_execution_failure_count(action); - break; } return 0; @@ -497,18 +492,59 @@ static int action_executor_rotate_session_handler(struct action_executor *execut } /* - * Mind the order of the declaration of list_lock vs target_session: + * Mind the order of the declaration of list_lock vs session: * the session list lock must always be released _after_ the release of * a session's reference (the destruction of a ref/locked_ref) to ensure * since the reference's release may unpublish the session from the list of * sessions. */ const auto list_lock = lttng::sessiond::lock_session_list(); - ltt_session::locked_ref session; - try { - session = ltt_session::find_locked_session( + const auto session = ltt_session::find_locked_session( LTTNG_OPTIONAL_GET(item->context.session_id)); + + if (session->destroyed) { + DBG("Session `%s` with id = %" PRIu64 + " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`", + session->name, + session->id, + get_action_name(action), + get_trigger_name(work_item->trigger)); + return 0; + } + + if (!is_trigger_allowed_for_session(work_item->trigger, session)) { + return 0; + } + + cmd_ret = (lttng_error_code) cmd_rotate_session( + session, nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED); + switch (cmd_ret) { + case LTTNG_OK: + DBG("Successfully started rotation of session `%s` on behalf of trigger `%s`", + session_name, + get_trigger_name(work_item->trigger)); + break; + case LTTNG_ERR_ROTATION_PENDING: + DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation is already ongoing", + session_name, + get_trigger_name(work_item->trigger)); + lttng_action_increase_execution_failure_count(action); + break; + case LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP: + case LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR: + DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation has already been completed since the last stop or clear", + session_name, + get_trigger_name(work_item->trigger)); + break; + default: + WARN("Failed to start a rotation of session `%s` on behalf of trigger `%s`: %s", + session_name, + get_trigger_name(work_item->trigger), + lttng_strerror(-cmd_ret)); + lttng_action_increase_execution_failure_count(action); + break; + } } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { DBG_FMT("Failed to execution trigger action: {}, action=`{}`, trigger_name=`{}`, location='{}'", ex.what(), @@ -517,50 +553,6 @@ static int action_executor_rotate_session_handler(struct action_executor *execut get_trigger_name(work_item->trigger), ex.source_location); lttng_action_increase_execution_failure_count(action); - return 0; - } - - if (session->destroyed) { - DBG("Session `%s` with id = %" PRIu64 - " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`", - session->name, - session->id, - get_action_name(action), - get_trigger_name(work_item->trigger)); - return 0; - } - - if (!is_trigger_allowed_for_session(work_item->trigger, session.get())) { - return 0; - } - - cmd_ret = (lttng_error_code) cmd_rotate_session( - session.get(), nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED); - switch (cmd_ret) { - case LTTNG_OK: - DBG("Successfully started rotation of session `%s` on behalf of trigger `%s`", - session_name, - get_trigger_name(work_item->trigger)); - break; - case LTTNG_ERR_ROTATION_PENDING: - DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation is already ongoing", - session_name, - get_trigger_name(work_item->trigger)); - lttng_action_increase_execution_failure_count(action); - break; - case LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP: - case LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR: - DBG("Attempted to start a rotation of session `%s` on behalf of trigger `%s` but a rotation has already been completed since the last stop or clear", - session_name, - get_trigger_name(work_item->trigger)); - break; - default: - WARN("Failed to start a rotation of session `%s` on behalf of trigger `%s`: %s", - session_name, - get_trigger_name(work_item->trigger), - lttng_strerror(-cmd_ret)); - lttng_action_increase_execution_failure_count(action); - break; } return 0; @@ -614,11 +606,40 @@ static int action_executor_snapshot_session_handler(struct action_executor *exec * sessions. */ const auto list_lock = lttng::sessiond::lock_session_list(); - ltt_session::locked_ref session; - try { - session = ltt_session::find_locked_session( + const auto session = ltt_session::find_locked_session( LTTNG_OPTIONAL_GET(item->context.session_id)); + + if (session->destroyed) { + DBG("Session `%s` with id = %" PRIu64 + " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`", + session->name, + session->id, + get_action_name(action), + get_trigger_name(work_item->trigger)); + return 0; + } + + if (!is_trigger_allowed_for_session(work_item->trigger, session)) { + return 0; + } + + cmd_ret = (lttng_error_code) cmd_snapshot_record(session, snapshot_output, 0); + switch (cmd_ret) { + case LTTNG_OK: + DBG("Successfully recorded snapshot of session `%s` on behalf of trigger `%s`", + session_name, + get_trigger_name(work_item->trigger)); + break; + default: + WARN("Failed to record snapshot of session `%s` on behalf of trigger `%s`: %s", + session_name, + get_trigger_name(work_item->trigger), + lttng_strerror(-cmd_ret)); + lttng_action_increase_execution_failure_count(action); + break; + } + } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { DBG_FMT("Failed to execution trigger action: {}, action=`{}`, trigger_name=`{}`, location='{}'", ex.what(), @@ -627,37 +648,6 @@ static int action_executor_snapshot_session_handler(struct action_executor *exec get_trigger_name(work_item->trigger), ex.source_location); lttng_action_increase_execution_failure_count(action); - return 0; - } - - if (session->destroyed) { - DBG("Session `%s` with id = %" PRIu64 - " is flagged as destroyed. Skipping: action = `%s`, trigger = `%s`", - session->name, - session->id, - get_action_name(action), - get_trigger_name(work_item->trigger)); - return 0; - } - - if (!is_trigger_allowed_for_session(work_item->trigger, session.get())) { - return 0; - } - - cmd_ret = (lttng_error_code) cmd_snapshot_record(session.get(), snapshot_output, 0); - switch (cmd_ret) { - case LTTNG_OK: - DBG("Successfully recorded snapshot of session `%s` on behalf of trigger `%s`", - session_name, - get_trigger_name(work_item->trigger)); - break; - default: - WARN("Failed to record snapshot of session `%s` on behalf of trigger `%s`: %s", - session_name, - get_trigger_name(work_item->trigger), - lttng_strerror(-cmd_ret)); - lttng_action_increase_execution_failure_count(action); - break; } return 0; diff --git a/src/bin/lttng-sessiond/clear.cpp b/src/bin/lttng-sessiond/clear.cpp index ced992594..b08cc8791 100644 --- a/src/bin/lttng-sessiond/clear.cpp +++ b/src/bin/lttng-sessiond/clear.cpp @@ -26,7 +26,7 @@ struct cmd_clear_session_reply_context { }; } /* namespace */ -static void cmd_clear_session_reply(const struct ltt_session *session, void *_reply_context) +static void cmd_clear_session_reply(const ltt_session::locked_ref& session, void *_reply_context) { int ret; ssize_t comm_ret; @@ -53,7 +53,7 @@ static void cmd_clear_session_reply(const struct ltt_session *session, void *_re free(_reply_context); } -int cmd_clear_session(struct ltt_session *session, int *sock_fd) +int cmd_clear_session(const ltt_session::locked_ref& session, int *sock_fd) { int ret = LTTNG_OK; struct cmd_clear_session_reply_context *reply_context = nullptr; diff --git a/src/bin/lttng-sessiond/clear.hpp b/src/bin/lttng-sessiond/clear.hpp index aca20d35a..b3618bfde 100644 --- a/src/bin/lttng-sessiond/clear.hpp +++ b/src/bin/lttng-sessiond/clear.hpp @@ -10,6 +10,6 @@ #include "session.hpp" -int cmd_clear_session(struct ltt_session *session, int *sock_fd); +int cmd_clear_session(const ltt_session::locked_ref& session, int *sock_fd); #endif /* CLEAT_H */ diff --git a/src/bin/lttng-sessiond/client.cpp b/src/bin/lttng-sessiond/client.cpp index fa368a90d..b4958e374 100644 --- a/src/bin/lttng-sessiond/client.cpp +++ b/src/bin/lttng-sessiond/client.cpp @@ -421,13 +421,12 @@ error: * function also applies the right modification on a per domain basis for the * trace files destination directory. */ -static int copy_session_consumer(int domain, struct ltt_session *session) +static int copy_session_consumer(int domain, const ltt_session::locked_ref& session) { int ret; const char *dir_name; struct consumer_output *consumer; - LTTNG_ASSERT(session); LTTNG_ASSERT(session->consumer); switch (domain) { @@ -481,12 +480,12 @@ error: /* * Create an UST session and add it to the session ust list. */ -static int create_ust_session(struct ltt_session *session, const struct lttng_domain *domain) +static int create_ust_session(const ltt_session::locked_ref& session, + const struct lttng_domain *domain) { int ret; struct ltt_ust_session *lus = nullptr; - LTTNG_ASSERT(session); LTTNG_ASSERT(domain); LTTNG_ASSERT(session->consumer); @@ -540,7 +539,7 @@ error: /* * Create a kernel tracer session then create the default channel. */ -static int create_kernel_session(struct ltt_session *session) +static int create_kernel_session(const ltt_session::locked_ref& session) { int ret; @@ -582,22 +581,23 @@ error_create: static unsigned int lttng_sessions_count(uid_t uid, gid_t gid __attribute__((unused))) { unsigned int i = 0; - struct ltt_session *session; + struct ltt_session *raw_session_ptr; const struct ltt_session_list *session_list = session_get_list(); DBG("Counting number of available session for UID %d", uid); - cds_list_for_each_entry (session, &session_list->head, list) { - if (!session_get(session)) { - continue; - } - session_lock(session); + cds_list_for_each_entry (raw_session_ptr, &session_list->head, list) { + auto session = [raw_session_ptr]() { + session_get(raw_session_ptr); + raw_session_ptr->lock(); + return ltt_session::locked_ref(*raw_session_ptr); + }(); + /* Only count the sessions the user can control. */ if (session_access_ok(session, uid) && !session->destroyed) { i++; } - session_unlock(session); - session_put(session); } + return i; } @@ -1111,10 +1111,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ std::unique_lock list_lock; /* * A locked_ref is typically "never null" (hence its name). However, due to the - * structure of this function, target_session remains null for commands that don't + * structure of this function, target_session remains unset for commands that don't * have a target session. */ - ltt_session::locked_ref target_session; + nonstd::optional target_session; /* Commands that DO NOT need a session. */ switch (cmd_ctx->lsm.cmd_type) { @@ -1146,8 +1146,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ */ list_lock = lttng::sessiond::lock_session_list(); try { - target_session = - ltt_session::find_locked_session(cmd_ctx->lsm.session.name); + target_session.emplace( + ltt_session::find_locked_session(cmd_ctx->lsm.session.name)); } catch (...) { std::throw_with_nested(lttng::ctl::error( fmt::format( @@ -1173,7 +1173,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ case LTTCOMM_SESSIOND_COMMAND_DISABLE_EVENT: switch (cmd_ctx->lsm.domain.type) { case LTTNG_DOMAIN_KERNEL: - if (!target_session->kernel_session) { + if (!(*target_session)->kernel_session) { return LTTNG_ERR_NO_CHANNEL; } break; @@ -1181,7 +1181,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_PYTHON: case LTTNG_DOMAIN_UST: - if (!target_session->ust_session) { + if (!(*target_session)->ust_session) { return LTTNG_ERR_NO_CHANNEL; goto error; } @@ -1225,8 +1225,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ /* Need a session for kernel command */ if (need_tracing_session) { - if (target_session->kernel_session == nullptr) { - ret = create_kernel_session(target_session.get()); + if ((*target_session)->kernel_session == nullptr) { + ret = create_kernel_session(*target_session); if (ret != LTTNG_OK) { ret = LTTNG_ERR_KERN_SESS_FAIL; goto error; @@ -1253,7 +1253,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ * the consumer output of the session if exist. */ ret = consumer_create_socket(&the_kconsumer_data, - target_session->kernel_session->consumer); + (*target_session)->kernel_session->consumer); if (ret < 0) { goto error; } @@ -1283,9 +1283,9 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ if (need_tracing_session) { /* Create UST session if none exist. */ - if (target_session->ust_session == nullptr) { + if ((*target_session)->ust_session == nullptr) { lttng_domain domain = cmd_ctx->lsm.domain; - ret = create_ust_session(target_session.get(), &domain); + ret = create_ust_session(*target_session, &domain); if (ret != LTTNG_OK) { goto error; } @@ -1317,7 +1317,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ * since it was set above and can ONLY be set in this thread. */ ret = consumer_create_socket(&the_ustconsumer64_data, - target_session->ust_session->consumer); + (*target_session)->ust_session->consumer); if (ret < 0) { goto error; } @@ -1347,7 +1347,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int *sock_ * since it was set above and can ONLY be set in this thread. */ ret = consumer_create_socket(&the_ustconsumer32_data, - target_session->ust_session->consumer); + (*target_session)->ust_session->consumer); if (ret < 0) { goto error; } @@ -1391,9 +1391,8 @@ skip_domain: * The root user can interact with all sessions. */ if (need_tracing_session) { - if (!session_access_ok(target_session.get(), - LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds)) || - target_session->destroyed) { + if (!session_access_ok(*target_session, LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds)) || + (*target_session)->destroyed) { ret = LTTNG_ERR_EPERM; goto error; } @@ -1408,7 +1407,7 @@ skip_domain: * Setup relayd if not done yet. If the relayd information was already * sent to the consumer, this call will gracefully return. */ - ret = cmd_setup_relayd(target_session.get()); + ret = cmd_setup_relayd(*target_session); if (ret != LTTNG_OK) { goto error; } @@ -1428,20 +1427,20 @@ skip_domain: } ret = cmd_add_context( - cmd_ctx, target_session, event_context, the_kernel_poll_pipe[1]); + cmd_ctx, *target_session, event_context, the_kernel_poll_pipe[1]); lttng_event_context_destroy(event_context); break; } case LTTCOMM_SESSIOND_COMMAND_DISABLE_CHANNEL: { - ret = cmd_disable_channel(target_session.get(), + ret = cmd_disable_channel(*target_session, cmd_ctx->lsm.domain.type, cmd_ctx->lsm.u.disable.channel_name); break; } case LTTCOMM_SESSIOND_COMMAND_ENABLE_CHANNEL: { - ret = cmd_enable_channel(cmd_ctx, target_session, *sock, the_kernel_poll_pipe[1]); + ret = cmd_enable_channel(cmd_ctx, *target_session, *sock, the_kernel_poll_pipe[1]); break; } case LTTCOMM_SESSIOND_COMMAND_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE: @@ -1538,10 +1537,10 @@ skip_domain: if (add_value) { ret = cmd_process_attr_tracker_inclusion_set_add_value( - target_session.get(), domain_type, process_attr, value); + *target_session, domain_type, process_attr, value); } else { ret = cmd_process_attr_tracker_inclusion_set_remove_value( - target_session.get(), domain_type, process_attr, value); + *target_session, domain_type, process_attr, value); } process_attr_value_destroy(value); error_add_remove_tracker_value: @@ -1558,7 +1557,7 @@ skip_domain: .process_attr_tracker_get_tracking_policy.process_attr; ret = cmd_process_attr_tracker_get_tracking_policy( - target_session.get(), domain_type, process_attr, &tracking_policy); + *target_session, domain_type, process_attr, &tracking_policy); if (ret != LTTNG_OK) { goto error; } @@ -1581,7 +1580,7 @@ skip_domain: .process_attr_tracker_set_tracking_policy.process_attr; ret = cmd_process_attr_tracker_set_tracking_policy( - target_session.get(), domain_type, process_attr, tracking_policy); + *target_session, domain_type, process_attr, tracking_policy); if (ret != LTTNG_OK) { goto error; } @@ -1598,7 +1597,7 @@ skip_domain: cmd_ctx->lsm.u.process_attr_tracker_get_inclusion_set.process_attr; ret = cmd_process_attr_tracker_get_inclusion_set( - target_session.get(), domain_type, process_attr, &values); + *target_session, domain_type, process_attr, &values); if (ret != LTTNG_OK) { goto error; } @@ -1643,14 +1642,14 @@ skip_domain: */ ret = cmd_ctx->lsm.cmd_type == LTTCOMM_SESSIOND_COMMAND_ENABLE_EVENT ? cmd_enable_event(cmd_ctx, - target_session, + *target_session, event, filter_expression, exclusions, bytecode, the_kernel_poll_pipe[1]) : cmd_disable_event(cmd_ctx, - target_session, + *target_session, event, filter_expression, bytecode, @@ -1764,7 +1763,7 @@ skip_domain: goto error; } - ret = cmd_set_consumer_uri(target_session.get(), nb_uri, uris); + ret = cmd_set_consumer_uri(*target_session, nb_uri, uris); free(uris); if (ret != LTTNG_OK) { goto error; @@ -1779,24 +1778,24 @@ skip_domain: * enabled time or size-based rotations, we have to make sure * the kernel tracer supports it. */ - if (!target_session->has_been_started && target_session->kernel_session && - (target_session->rotate_timer_period || target_session->rotate_size) && + if (!(*target_session)->has_been_started && (*target_session)->kernel_session && + ((*target_session)->rotate_timer_period || (*target_session)->rotate_size) && !check_rotate_compatible()) { DBG("Kernel tracer version is not compatible with the rotation feature"); ret = LTTNG_ERR_ROTATION_WRONG_VERSION; goto error; } - ret = cmd_start_trace(target_session.get()); + ret = cmd_start_trace(*target_session); break; } case LTTCOMM_SESSIOND_COMMAND_STOP_TRACE: { - ret = cmd_stop_trace(target_session.get()); + ret = cmd_stop_trace(*target_session); break; } case LTTCOMM_SESSIOND_COMMAND_DESTROY_SESSION: { - ret = cmd_destroy_session(target_session.get(), sock); + ret = cmd_destroy_session(*target_session, sock); break; } case LTTCOMM_SESSIOND_COMMAND_LIST_DOMAINS: @@ -1804,7 +1803,7 @@ skip_domain: ssize_t nb_dom; struct lttng_domain *domains = nullptr; - nb_dom = cmd_list_domains(target_session.get(), &domains); + nb_dom = cmd_list_domains(*target_session, &domains); if (nb_dom < 0) { /* Return value is a negative lttng_error_code. */ ret = -nb_dom; @@ -1830,7 +1829,7 @@ skip_domain: original_payload_size = cmd_ctx->reply_payload.buffer.size; ret_code = cmd_list_channels( - cmd_ctx->lsm.domain.type, target_session.get(), &cmd_ctx->reply_payload); + cmd_ctx->lsm.domain.type, *target_session, &cmd_ctx->reply_payload); if (ret_code != LTTNG_OK) { ret = (int) ret_code; goto error; @@ -1855,7 +1854,7 @@ skip_domain: original_payload_size = cmd_ctx->reply_payload.buffer.size; ret_code = cmd_list_events(cmd_ctx->lsm.domain.type, - target_session.get(), + *target_session, cmd_ctx->lsm.u.list.channel_name, &cmd_ctx->reply_payload); if (ret_code != LTTNG_OK) { @@ -1915,10 +1914,8 @@ skip_domain: goto error; } - ret = cmd_register_consumer(target_session.get(), - cmd_ctx->lsm.domain.type, - cmd_ctx->lsm.u.reg.path, - cdata); + ret = cmd_register_consumer( + *target_session, cmd_ctx->lsm.domain.type, cmd_ctx->lsm.u.reg.path, cdata); break; } case LTTCOMM_SESSIOND_COMMAND_KERNEL_TRACER_STATUS: @@ -1942,7 +1939,7 @@ skip_domain: int pending_ret; uint8_t pending_ret_byte; - pending_ret = cmd_data_pending(target_session.get()); + pending_ret = cmd_data_pending(*target_session); /* * FIXME @@ -1980,7 +1977,7 @@ skip_domain: struct lttcomm_lttng_output_id reply; lttng_snapshot_output output = cmd_ctx->lsm.u.snapshot_output.output; - ret = cmd_snapshot_add_output(target_session.get(), &output, &snapshot_id); + ret = cmd_snapshot_add_output(*target_session, &output, &snapshot_id); if (ret != LTTNG_OK) { goto error; } @@ -1995,7 +1992,7 @@ skip_domain: case LTTCOMM_SESSIOND_COMMAND_SNAPSHOT_DEL_OUTPUT: { lttng_snapshot_output output = cmd_ctx->lsm.u.snapshot_output.output; - ret = cmd_snapshot_del_output(target_session.get(), &output); + ret = cmd_snapshot_del_output(*target_session, &output); break; } case LTTCOMM_SESSIOND_COMMAND_SNAPSHOT_LIST_OUTPUT: @@ -2003,7 +2000,7 @@ skip_domain: ssize_t nb_output; struct lttng_snapshot_output *outputs = nullptr; - nb_output = cmd_snapshot_list_outputs(target_session.get(), &outputs); + nb_output = cmd_snapshot_list_outputs(*target_session, &outputs); if (nb_output < 0) { ret = -nb_output; goto error; @@ -2020,10 +2017,10 @@ skip_domain: case LTTCOMM_SESSIOND_COMMAND_SNAPSHOT_RECORD: { lttng_snapshot_output output = cmd_ctx->lsm.u.snapshot_record.output; - ret = cmd_snapshot_record(target_session.get(), &output, 0); // RFC: set to zero - // since it's ignored - // by - // cmd_snapshot_record + ret = cmd_snapshot_record(*target_session, &output, 0); // RFC: set to zero + // since it's ignored + // by + // cmd_snapshot_record break; } case LTTCOMM_SESSIOND_COMMAND_CREATE_SESSION_EXT: @@ -2062,18 +2059,18 @@ skip_domain: } case LTTCOMM_SESSIOND_COMMAND_SET_SESSION_SHM_PATH: { - ret = cmd_set_session_shm_path(target_session.get(), + ret = cmd_set_session_shm_path(*target_session, cmd_ctx->lsm.u.set_shm_path.shm_path); break; } case LTTCOMM_SESSIOND_COMMAND_REGENERATE_METADATA: { - ret = cmd_regenerate_metadata(target_session.get()); + ret = cmd_regenerate_metadata(*target_session); break; } case LTTCOMM_SESSIOND_COMMAND_REGENERATE_STATEDUMP: { - ret = cmd_regenerate_statedump(target_session.get()); + ret = cmd_regenerate_statedump(*target_session); break; } case LTTCOMM_SESSIOND_COMMAND_REGISTER_TRIGGER: @@ -2132,16 +2129,16 @@ skip_domain: { struct lttng_rotate_session_return rotate_return; - DBG("Client rotate session \"%s\"", target_session->name); + DBG("Client rotate session \"%s\"", (*target_session)->name); memset(&rotate_return, 0, sizeof(rotate_return)); - if (target_session->kernel_session && !check_rotate_compatible()) { + if ((*target_session)->kernel_session && !check_rotate_compatible()) { DBG("Kernel tracer version is not compatible with the rotation feature"); ret = LTTNG_ERR_ROTATION_WRONG_VERSION; goto error; } - ret = cmd_rotate_session(target_session.get(), + ret = cmd_rotate_session(*target_session, &rotate_return, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED); @@ -2160,7 +2157,7 @@ skip_domain: struct lttng_rotation_get_info_return get_info_return; memset(&get_info_return, 0, sizeof(get_info_return)); - ret = cmd_rotate_get_info(target_session.get(), + ret = cmd_rotate_get_info(*target_session, &get_info_return, cmd_ctx->lsm.u.get_rotation_info.rotation_id); if (ret < 0) { @@ -2179,7 +2176,7 @@ skip_domain: enum lttng_rotation_schedule_type schedule_type; uint64_t value; - if (target_session->kernel_session && !check_rotate_compatible()) { + if ((*target_session)->kernel_session && !check_rotate_compatible()) { DBG("Kernel tracer version does not support session rotations"); ret = LTTNG_ERR_ROTATION_WRONG_VERSION; goto error; @@ -2191,7 +2188,7 @@ skip_domain: value = cmd_ctx->lsm.u.rotation_set_schedule.value; ret = cmd_rotation_set_schedule( - target_session.get(), set_schedule, schedule_type, value); + *target_session, set_schedule, schedule_type, value); if (ret != LTTNG_OK) { goto error; } @@ -2202,10 +2199,10 @@ skip_domain: { lttng_session_list_schedules_return schedules; - schedules.periodic.set = !!target_session->rotate_timer_period; - schedules.periodic.value = target_session->rotate_timer_period; - schedules.size.set = !!target_session->rotate_size; - schedules.size.value = target_session->rotate_size; + schedules.periodic.set = !!(*target_session)->rotate_timer_period; + schedules.periodic.value = (*target_session)->rotate_timer_period; + schedules.size.set = !!(*target_session)->rotate_size; + schedules.size.value = (*target_session)->rotate_size; setup_lttng_msg_no_cmd_header(cmd_ctx, &schedules, sizeof(schedules)); @@ -2214,7 +2211,7 @@ skip_domain: } case LTTCOMM_SESSIOND_COMMAND_CLEAR_SESSION: { - ret = cmd_clear_session(target_session.get(), sock); + ret = cmd_clear_session(*target_session, sock); break; } case LTTCOMM_SESSIOND_COMMAND_LIST_TRIGGERS: diff --git a/src/bin/lttng-sessiond/cmd.cpp b/src/bin/lttng-sessiond/cmd.cpp index 3f79ee2bb..ee96fc828 100644 --- a/src/bin/lttng-sessiond/cmd.cpp +++ b/src/bin/lttng-sessiond/cmd.cpp @@ -12,6 +12,7 @@ #include "buffer-registry.hpp" #include "channel.hpp" #include "cmd.hpp" +#include "consumer-output.hpp" #include "consumer.hpp" #include "event-notifier-error-accounting.hpp" #include "event.hpp" @@ -133,13 +134,13 @@ static enum lttng_error_code cmd_enable_channel_internal(ltt_session::locked_ref * Create a session path used by list_lttng_sessions for the case that the * session consumer is on the network. */ -static int build_network_session_path(char *dst, size_t size, struct ltt_session *session) +static int +build_network_session_path(char *dst, size_t size, const ltt_session::locked_ref& session) { int ret, kdata_port, udata_port; struct lttng_uri *kuri = nullptr, *uuri = nullptr, *uri = nullptr; char tmp_uurl[PATH_MAX], tmp_urls[PATH_MAX]; - LTTNG_ASSERT(session); LTTNG_ASSERT(dst); memset(tmp_urls, 0, sizeof(tmp_urls)); @@ -215,7 +216,7 @@ error: * Get run-time attributes if the session has been started (discarded events, * lost packets). */ -static int get_kernel_runtime_stats(struct ltt_session *session, +static int get_kernel_runtime_stats(const ltt_session::locked_ref& session, struct ltt_kernel_channel *kchan, uint64_t *discarded_events, uint64_t *lost_packets) @@ -249,7 +250,7 @@ end: * Get run-time attributes if the session has been started (discarded events, * lost packets). */ -static int get_ust_runtime_stats(struct ltt_session *session, +static int get_ust_runtime_stats(const ltt_session::locked_ref& session, struct ltt_ust_channel *uchan, uint64_t *discarded_events, uint64_t *lost_packets) @@ -645,7 +646,7 @@ end: * Add URI so the consumer output object. Set the correct path depending on the * domain adding the default trace directory. */ -static enum lttng_error_code add_uri_to_consumer(const struct ltt_session *session, +static enum lttng_error_code add_uri_to_consumer(const ltt_session::locked_ref& session, struct consumer_output *consumer, struct lttng_uri *uri, enum lttng_domain_type domain) @@ -1013,7 +1014,7 @@ error: * the relayd and send them to the right domain consumer. Consumer type MUST be * network. */ -int cmd_setup_relayd(struct ltt_session *session) +int cmd_setup_relayd(const ltt_session::locked_ref& session) { int ret = LTTNG_OK; struct ltt_ust_session *usess; @@ -1022,8 +1023,6 @@ int cmd_setup_relayd(struct ltt_session *session) struct lttng_ht_iter iter; LTTNG_OPTIONAL(uint64_t) current_chunk_id = {}; - LTTNG_ASSERT(session); - usess = session->ust_session; ksess = session->kernel_session; @@ -1224,7 +1223,7 @@ error: /* * Command LTTNG_DISABLE_CHANNEL processed by the client thread. */ -int cmd_disable_channel(struct ltt_session *session, +int cmd_disable_channel(const ltt_session::locked_ref& session, enum lttng_domain_type domain, char *channel_name) { @@ -1332,7 +1331,7 @@ static enum lttng_error_code cmd_enable_channel_internal(ltt_session::locked_ref int wpipe) { enum lttng_error_code ret_code; - struct ltt_ust_session *usess = session.get()->ust_session; + struct ltt_ust_session *usess = session->ust_session; struct lttng_ht *chan_ht; size_t len; struct lttng_channel *attr = nullptr; @@ -1363,8 +1362,8 @@ static enum lttng_error_code cmd_enable_channel_internal(ltt_session::locked_ref * live timer does the same thing but sends also synchronisation * beacons for inactive streams. */ - if (session.get()->live_timer > 0) { - attr->attr.live_timer_interval = session.get()->live_timer; + if (session->live_timer > 0) { + attr->attr.live_timer_interval = session->live_timer; attr->attr.switch_timer_interval = 0; } @@ -1378,7 +1377,7 @@ static enum lttng_error_code cmd_enable_channel_internal(ltt_session::locked_ref "Setting the monitor interval timer to 0 " "(disabled) for channel '%s' of session '%s'", attr->name, - session.get()->name); + session->name); lttng_channel_set_monitor_timer_interval(attr, 0); } break; @@ -1509,7 +1508,7 @@ end: } enum lttng_error_code -cmd_process_attr_tracker_get_tracking_policy(struct ltt_session *session, +cmd_process_attr_tracker_get_tracking_policy(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, enum lttng_tracking_policy *policy) @@ -1546,7 +1545,7 @@ end: } enum lttng_error_code -cmd_process_attr_tracker_set_tracking_policy(struct ltt_session *session, +cmd_process_attr_tracker_set_tracking_policy(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, enum lttng_tracking_policy policy) @@ -1589,7 +1588,7 @@ end: } enum lttng_error_code -cmd_process_attr_tracker_inclusion_set_add_value(struct ltt_session *session, +cmd_process_attr_tracker_inclusion_set_add_value(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, const struct process_attr_value *value) @@ -1622,7 +1621,7 @@ end: } enum lttng_error_code -cmd_process_attr_tracker_inclusion_set_remove_value(struct ltt_session *session, +cmd_process_attr_tracker_inclusion_set_remove_value(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, const struct process_attr_value *value) @@ -1655,7 +1654,7 @@ end: } enum lttng_error_code -cmd_process_attr_tracker_get_inclusion_set(struct ltt_session *session, +cmd_process_attr_tracker_get_inclusion_set(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, struct lttng_process_attr_values **values) @@ -1720,7 +1719,7 @@ int cmd_disable_event(struct command_ctx *cmd_ctx, struct lttng_event_exclusion *exclusion) { int ret; - ltt_session& session = *locked_session.get(); + const ltt_session& session = *locked_session; const char *event_name; const char *channel_name = cmd_ctx->lsm.u.disable.channel_name; const enum lttng_domain_type domain = cmd_ctx->lsm.domain.type; @@ -1912,7 +1911,7 @@ int cmd_add_context(struct command_ctx *cmd_ctx, { int ret, chan_kern_created = 0, chan_ust_created = 0; const enum lttng_domain_type domain = cmd_ctx->lsm.domain.type; - const struct ltt_session& session = *locked_session.get(); + const struct ltt_session& session = *locked_session; const char *channel_name = cmd_ctx->lsm.u.context.channel_name; /* @@ -2075,7 +2074,7 @@ static int _cmd_enable_event(ltt_session::locked_ref& locked_session, { int ret = 0, channel_created = 0; struct lttng_channel *attr = nullptr; - ltt_session& session = *locked_session.get(); + ltt_session& session = *locked_session; LTTNG_ASSERT(event); LTTNG_ASSERT(channel_name); @@ -2716,10 +2715,8 @@ end: /* * Command LTTNG_START_TRACE processed by the client thread. - * - * Called with session mutex held. */ -int cmd_start_trace(struct ltt_session *session) +int cmd_start_trace(const ltt_session::locked_ref& session) { enum lttng_error_code ret; unsigned long nb_chan = 0; @@ -2728,8 +2725,6 @@ int cmd_start_trace(struct ltt_session *session) const bool session_rotated_after_last_stop = session->rotated_after_last_stop; const bool session_cleared_after_last_stop = session->cleared_after_last_stop; - LTTNG_ASSERT(session); - /* Ease our life a bit ;) */ ksession = session->kernel_session; usess = session->ust_session; @@ -2880,14 +2875,12 @@ end: /* * Command LTTNG_STOP_TRACE processed by the client thread. */ -int cmd_stop_trace(struct ltt_session *session) +int cmd_stop_trace(const ltt_session::locked_ref& session) { int ret; struct ltt_kernel_session *ksession; struct ltt_ust_session *usess; - LTTNG_ASSERT(session); - DBG("Begin stop session \"%s\" (id %" PRIu64 ")", session->name, session->id); /* Short cut */ ksession = session->kernel_session; @@ -2925,8 +2918,9 @@ error: * Set the base_path of the session only if subdir of a control uris is set. * Return LTTNG_OK on success, otherwise LTTNG_ERR_*. */ -static int -set_session_base_path_from_uris(struct ltt_session *session, size_t nb_uri, struct lttng_uri *uris) +static int set_session_base_path_from_uris(const ltt_session::locked_ref& session, + size_t nb_uri, + struct lttng_uri *uris) { int ret; size_t i; @@ -2963,13 +2957,14 @@ error: /* * Command LTTNG_SET_CONSUMER_URI processed by the client thread. */ -int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri, struct lttng_uri *uris) +int cmd_set_consumer_uri(const ltt_session::locked_ref& session, + size_t nb_uri, + struct lttng_uri *uris) { int ret, i; struct ltt_kernel_session *ksess = session->kernel_session; struct ltt_ust_session *usess = session->ust_session; - LTTNG_ASSERT(session); LTTNG_ASSERT(uris); LTTNG_ASSERT(nb_uri > 0); @@ -3044,7 +3039,7 @@ error: } static enum lttng_error_code -set_session_output_from_descriptor(struct ltt_session *session, +set_session_output_from_descriptor(const ltt_session::locked_ref& session, const struct lttng_session_descriptor *descriptor) { int ret; @@ -3161,8 +3156,13 @@ cmd_create_session_from_descriptor(struct lttng_session_descriptor *descriptor, /* Announce the session's destruction to the notification thread when it is destroyed. */ ret = session_add_destroy_notifier( - new_session, - [](const struct ltt_session *session, void *user_data __attribute__((unused))) { + [new_session]() { + session_get(new_session); + new_session->lock(); + return ltt_session::locked_ref(*new_session); + }(), + [](const ltt_session::locked_ref& session, + void *user_data __attribute__((unused))) { (void) notification_thread_command_remove_session( the_notification_thread_handle, session->id); }, @@ -3212,7 +3212,13 @@ cmd_create_session_from_descriptor(struct lttng_session_descriptor *descriptor, break; } - ret_code = set_session_output_from_descriptor(new_session, descriptor); + ret_code = set_session_output_from_descriptor( + [new_session]() { + session_get(new_session); + new_session->lock(); + return ltt_session::locked_ref(*new_session); + }(), + descriptor); if (ret_code != LTTNG_OK) { goto end; } @@ -3315,7 +3321,7 @@ error: return ret_code; } -static void cmd_destroy_session_reply(const struct ltt_session *session, void *_reply_context) +static void cmd_destroy_session_reply(const ltt_session::locked_ref& session, void *_reply_context) { int ret; ssize_t comm_ret; @@ -3400,7 +3406,7 @@ error: * * Called with session lock held. */ -int cmd_destroy_session(struct ltt_session *session, int *sock_fd) +int cmd_destroy_session(const ltt_session::locked_ref& session, int *sock_fd) { int ret; enum lttng_error_code destruction_last_error = LTTNG_OK; @@ -3416,9 +3422,6 @@ int cmd_destroy_session(struct ltt_session *session, int *sock_fd) reply_context->reply_sock_fd = *sock_fd; } - /* Safety net */ - LTTNG_ASSERT(session); - DBG("Begin destroy session %s (id %" PRIu64 ")", session->name, session->id); if (session->active) { DBG("Session \"%s\" is active, attempting to stop it before destroying it", @@ -3556,7 +3559,7 @@ int cmd_destroy_session(struct ltt_session *session, int *sock_fd) * still holds a reference to the session, thus delaying its destruction * _at least_ up to the point when that reference is released. */ - session_destroy(session); + session_destroy(&session.get()); if (reply_context) { reply_context->destruction_status = destruction_last_error; ret = session_add_destroy_notifier( @@ -3576,7 +3579,7 @@ end: /* * Command LTTNG_REGISTER_CONSUMER processed by the client thread. */ -int cmd_register_consumer(struct ltt_session *session, +int cmd_register_consumer(const ltt_session::locked_ref& session, enum lttng_domain_type domain, const char *sock_path, struct consumer_data *cdata) @@ -3584,7 +3587,6 @@ int cmd_register_consumer(struct ltt_session *session, int ret, sock; struct consumer_socket *socket = nullptr; - LTTNG_ASSERT(session); LTTNG_ASSERT(cdata); LTTNG_ASSERT(sock_path); @@ -3656,7 +3658,7 @@ error: /* * Command LTTNG_LIST_DOMAINS processed by the client thread. */ -ssize_t cmd_list_domains(struct ltt_session *session, struct lttng_domain **domains) +ssize_t cmd_list_domains(const ltt_session::locked_ref& session, struct lttng_domain **domains) { int ret, index = 0; ssize_t nb_dom = 0; @@ -3732,7 +3734,7 @@ error: * Command LTTNG_LIST_CHANNELS processed by the client thread. */ enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain, - struct ltt_session *session, + const ltt_session::locked_ref& session, struct lttng_payload *payload) { int ret = 0; @@ -3741,8 +3743,7 @@ enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain, size_t cmd_header_offset; enum lttng_error_code ret_code; - assert(session); - assert(payload); + LTTNG_ASSERT(payload); DBG("Listing channels for session %s", session->name); @@ -3872,7 +3873,7 @@ end: * Command LTTNG_LIST_EVENTS processed by the client thread. */ enum lttng_error_code cmd_list_events(enum lttng_domain_type domain, - struct ltt_session *session, + const ltt_session::locked_ref& session, char *channel_name, struct lttng_payload *reply_payload) { @@ -3966,7 +3967,7 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, { int ret; unsigned int i = 0; - struct ltt_session *session; + struct ltt_session *raw_session_ptr; struct ltt_session_list *list = session_get_list(); struct lttng_session_extended *extended = (typeof(extended)) (&sessions[session_count]); @@ -3975,15 +3976,17 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, * Iterate over session list and append data after the control struct in * the buffer. */ - cds_list_for_each_entry (session, &list->head, list) { - if (!session_get(session)) { - continue; - } + cds_list_for_each_entry (raw_session_ptr, &list->head, list) { + auto session = [raw_session_ptr]() { + session_get(raw_session_ptr); + raw_session_ptr->lock(); + return ltt_session::locked_ref(*raw_session_ptr); + }(); + /* * Only list the sessions the user can control. */ if (!session_access_ok(session, uid) || session->destroyed) { - session_put(session); continue; } @@ -4003,7 +4006,6 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, } if (ret < 0) { PERROR("snprintf session path"); - session_put(session); continue; } @@ -4015,7 +4017,6 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, extended[i].creation_time.value = (uint64_t) session->creation_time; extended[i].creation_time.is_set = 1; i++; - session_put(session); } } @@ -4036,14 +4037,12 @@ enum lttng_error_code cmd_kernel_tracer_status(enum lttng_kernel_tracer_status * * Command LTTNG_DATA_PENDING returning 0 if the data is NOT pending meaning * ready for trace analysis (or any kind of reader) or else 1 for pending data. */ -int cmd_data_pending(struct ltt_session *session) +int cmd_data_pending(const ltt_session::locked_ref& session) { int ret; struct ltt_kernel_session *ksess = session->kernel_session; struct ltt_ust_session *usess = session->ust_session; - LTTNG_ASSERT(session); - DBG("Data pending for session %s", session->name); /* Session MUST be stopped to ask for data availability. */ @@ -4102,14 +4101,13 @@ error: * * Return LTTNG_OK on success or else a LTTNG_ERR code. */ -int cmd_snapshot_add_output(struct ltt_session *session, +int cmd_snapshot_add_output(const ltt_session::locked_ref& session, const struct lttng_snapshot_output *output, uint32_t *id) { int ret; struct snapshot_output *new_output; - LTTNG_ASSERT(session); LTTNG_ASSERT(output); DBG("Cmd snapshot add output for session %s", session->name); @@ -4174,12 +4172,12 @@ error: * * Return LTTNG_OK on success or else a LTTNG_ERR code. */ -int cmd_snapshot_del_output(struct ltt_session *session, const struct lttng_snapshot_output *output) +int cmd_snapshot_del_output(const ltt_session::locked_ref& session, + const struct lttng_snapshot_output *output) { int ret; struct snapshot_output *sout = nullptr; - LTTNG_ASSERT(session); LTTNG_ASSERT(output); lttng::urcu::read_lock_guard read_lock; @@ -4222,7 +4220,7 @@ error: * * Return the size of the newly allocated outputs or a negative LTTNG_ERR code. */ -ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, +ssize_t cmd_snapshot_list_outputs(const ltt_session::locked_ref& session, struct lttng_snapshot_output **outputs) { int ret, idx = 0; @@ -4230,7 +4228,6 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, struct lttng_ht_iter iter; struct snapshot_output *output; - LTTNG_ASSERT(session); LTTNG_ASSERT(outputs); DBG("Cmd snapshot list outputs for session %s", session->name); @@ -4315,12 +4312,10 @@ end: * * Return 0 if the metadata can be generated, a LTTNG_ERR code otherwise. */ -static int check_regenerate_metadata_support(struct ltt_session *session) +static int check_regenerate_metadata_support(const ltt_session::locked_ref& session) { int ret; - LTTNG_ASSERT(session); - if (session->live_timer != 0) { ret = LTTNG_ERR_LIVE_SESSION; goto end; @@ -4362,12 +4357,10 @@ end: * * Return LTTNG_OK on success or else a LTTNG_ERR code. */ -int cmd_regenerate_metadata(struct ltt_session *session) +int cmd_regenerate_metadata(const ltt_session::locked_ref& session) { int ret; - LTTNG_ASSERT(session); - ret = check_regenerate_metadata_support(session); if (ret) { goto end; @@ -4402,12 +4395,10 @@ end: * * Return LTTNG_OK on success or else a LTTNG_ERR code. */ -int cmd_regenerate_statedump(struct ltt_session *session) +int cmd_regenerate_statedump(const ltt_session::locked_ref& session) { int ret; - LTTNG_ASSERT(session); - if (!session->active) { ret = LTTNG_ERR_SESSION_NOT_STARTED; goto end; @@ -4940,7 +4931,7 @@ end: * Return LTTNG_OK on success or a LTTNG_ERR code. */ static enum lttng_error_code set_relayd_for_snapshot(struct consumer_output *output, - const struct ltt_session *session) + const ltt_session::locked_ref& session) { enum lttng_error_code status = LTTNG_OK; struct lttng_ht_iter iter; @@ -4949,7 +4940,6 @@ static enum lttng_error_code set_relayd_for_snapshot(struct consumer_output *out const char *base_path; LTTNG_ASSERT(output); - LTTNG_ASSERT(session); DBG2("Set relayd object from snapshot output"); @@ -5019,14 +5009,12 @@ error: */ static enum lttng_error_code record_kernel_snapshot(struct ltt_kernel_session *ksess, const struct consumer_output *output, - const struct ltt_session *session, uint64_t nb_packets_per_stream) { enum lttng_error_code status; LTTNG_ASSERT(ksess); LTTNG_ASSERT(output); - LTTNG_ASSERT(session); status = kernel_snapshot_record(ksess, output, nb_packets_per_stream); return status; @@ -5039,20 +5027,18 @@ static enum lttng_error_code record_kernel_snapshot(struct ltt_kernel_session *k */ static enum lttng_error_code record_ust_snapshot(struct ltt_ust_session *usess, const struct consumer_output *output, - const struct ltt_session *session, uint64_t nb_packets_per_stream) { enum lttng_error_code status; LTTNG_ASSERT(usess); LTTNG_ASSERT(output); - LTTNG_ASSERT(session); status = ust_app_snapshot_record(usess, output, nb_packets_per_stream); return status; } -static uint64_t get_session_size_one_more_packet_per_stream(const struct ltt_session *session, +static uint64_t get_session_size_one_more_packet_per_stream(const ltt_session::locked_ref& session, uint64_t cur_nr_packets) { uint64_t tot_size = 0; @@ -5102,7 +5088,7 @@ static uint64_t get_session_size_one_more_packet_per_stream(const struct ltt_ses * an approximation: for instance, applications could appear/disappear * in between this call and actually grabbing data. */ -static int64_t get_session_nb_packets_per_stream(const struct ltt_session *session, +static int64_t get_session_nb_packets_per_stream(const ltt_session::locked_ref& session, uint64_t max_size) { int64_t size_left; @@ -5135,7 +5121,7 @@ static int64_t get_session_nb_packets_per_stream(const struct ltt_session *sessi return cur_nb_packets; } -static enum lttng_error_code snapshot_record(struct ltt_session *session, +static enum lttng_error_code snapshot_record(const ltt_session::locked_ref& session, const struct snapshot_output *snapshot_output) { int64_t nb_packets_per_stream; @@ -5248,7 +5234,6 @@ static enum lttng_error_code snapshot_record(struct ltt_session *session, if (session->kernel_session) { ret_code = record_kernel_snapshot(session->kernel_session, snapshot_kernel_consumer_output, - session, nb_packets_per_stream); if (ret_code != LTTNG_OK) { goto error_close_trace_chunk; @@ -5256,10 +5241,8 @@ static enum lttng_error_code snapshot_record(struct ltt_session *session, } if (session->ust_session) { - ret_code = record_ust_snapshot(session->ust_session, - snapshot_ust_consumer_output, - session, - nb_packets_per_stream); + ret_code = record_ust_snapshot( + session->ust_session, snapshot_ust_consumer_output, nb_packets_per_stream); if (ret_code != LTTNG_OK) { goto error_close_trace_chunk; } @@ -5305,7 +5288,7 @@ error: * * Return LTTNG_OK on success or else a LTTNG_ERR code. */ -int cmd_snapshot_record(struct ltt_session *session, +int cmd_snapshot_record(const ltt_session::locked_ref& session, const struct lttng_snapshot_output *output, int wait __attribute__((unused))) { @@ -5315,7 +5298,6 @@ int cmd_snapshot_record(struct ltt_session *session, char datetime[16]; struct snapshot_output *tmp_output = nullptr; - LTTNG_ASSERT(session); LTTNG_ASSERT(output); DBG("Cmd snapshot record for session %s", session->name); @@ -5436,11 +5418,8 @@ error: /* * Command LTTNG_SET_SESSION_SHM_PATH processed by the client thread. */ -int cmd_set_session_shm_path(struct ltt_session *session, const char *shm_path) +int cmd_set_session_shm_path(const ltt_session::locked_ref& session, const char *shm_path) { - /* Safety net */ - LTTNG_ASSERT(session); - /* * Can only set shm path before session is started. */ @@ -5462,7 +5441,7 @@ int cmd_set_session_shm_path(struct ltt_session *session, const char *shm_path) * * Returns LTTNG_OK on success or else a negative LTTng error code. */ -int cmd_rotate_session(struct ltt_session *session, +int cmd_rotate_session(const ltt_session::locked_ref& session, struct lttng_rotate_session_return *rotate_return, bool quiet_rotation, enum lttng_trace_chunk_command_type command) @@ -5476,8 +5455,6 @@ int cmd_rotate_session(struct ltt_session *session, bool failed_to_rotate = false; enum lttng_error_code rotation_fail_code = LTTNG_OK; - LTTNG_ASSERT(session); - if (!session->has_been_started) { cmd_ret = LTTNG_ERR_START_SESSION_ONCE; goto end; @@ -5637,7 +5614,7 @@ end: ret = (cmd_ret == LTTNG_OK) ? cmd_ret : -((int) cmd_ret); return ret; error: - if (session_reset_rotation_state(*session, LTTNG_ROTATION_STATE_ERROR)) { + if (session_reset_rotation_state(session, LTTNG_ROTATION_STATE_ERROR)) { ERR("Failed to reset rotation state of session \"%s\"", session->name); } goto end; @@ -5650,7 +5627,7 @@ error: * * Return LTTNG_OK on success or else an LTTNG_ERR code. */ -int cmd_rotate_get_info(struct ltt_session *session, +int cmd_rotate_get_info(const ltt_session::locked_ref& session, struct lttng_rotation_get_info_return *info_return, uint64_t rotation_id) { @@ -5801,7 +5778,7 @@ end: * * Return LTTNG_OK on success or else a positive LTTNG_ERR code. */ -int cmd_rotation_set_schedule(struct ltt_session *session, +int cmd_rotation_set_schedule(const ltt_session::locked_ref& session, bool activate, enum lttng_rotation_schedule_type schedule_type, uint64_t new_value) @@ -5809,8 +5786,6 @@ int cmd_rotation_set_schedule(struct ltt_session *session, int ret; uint64_t *parameter_value; - LTTNG_ASSERT(session); - DBG("Cmd rotate set schedule session %s", session->name); if (session->live_timer || !session->output_traces) { diff --git a/src/bin/lttng-sessiond/cmd.hpp b/src/bin/lttng-sessiond/cmd.hpp index 7e5184a21..6b6dfedf5 100644 --- a/src/bin/lttng-sessiond/cmd.hpp +++ b/src/bin/lttng-sessiond/cmd.hpp @@ -13,6 +13,7 @@ #include "lttng-sessiond.hpp" #include "lttng/tracker.h" #include "session.hpp" +#include "snapshot-output.hpp" #include @@ -45,10 +46,10 @@ void cmd_init(); enum lttng_error_code cmd_create_session(struct command_ctx *cmd_ctx, int sock, struct lttng_session_descriptor **return_descriptor); -int cmd_destroy_session(struct ltt_session *session, int *sock_fd); +int cmd_destroy_session(const ltt_session::locked_ref& session, int *sock_fd); /* Channel commands */ -int cmd_disable_channel(struct ltt_session *session, +int cmd_disable_channel(const ltt_session::locked_ref& session, enum lttng_domain_type domain, char *channel_name); int cmd_enable_channel(struct command_ctx *cmd_ctx, @@ -58,27 +59,27 @@ int cmd_enable_channel(struct command_ctx *cmd_ctx, /* Process attribute tracker commands */ enum lttng_error_code -cmd_process_attr_tracker_get_tracking_policy(struct ltt_session *session, +cmd_process_attr_tracker_get_tracking_policy(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, enum lttng_tracking_policy *policy); enum lttng_error_code -cmd_process_attr_tracker_set_tracking_policy(struct ltt_session *session, +cmd_process_attr_tracker_set_tracking_policy(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, enum lttng_tracking_policy policy); enum lttng_error_code -cmd_process_attr_tracker_inclusion_set_add_value(struct ltt_session *session, +cmd_process_attr_tracker_inclusion_set_add_value(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, const struct process_attr_value *value); enum lttng_error_code -cmd_process_attr_tracker_inclusion_set_remove_value(struct ltt_session *session, +cmd_process_attr_tracker_inclusion_set_remove_value(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, const struct process_attr_value *value); enum lttng_error_code -cmd_process_attr_tracker_get_inclusion_set(struct ltt_session *session, +cmd_process_attr_tracker_get_inclusion_set(const ltt_session::locked_ref& session, enum lttng_domain_type domain, enum lttng_process_attr process_attr, struct lttng_process_attr_values **values); @@ -108,54 +109,53 @@ int cmd_enable_event(struct command_ctx *cmd_ctx, int wpipe); /* Trace session action commands */ -int cmd_start_trace(struct ltt_session *session); -int cmd_stop_trace(struct ltt_session *session); +int cmd_start_trace(const ltt_session::locked_ref& session); +int cmd_stop_trace(const ltt_session::locked_ref& session); /* Consumer commands */ -int cmd_register_consumer(struct ltt_session *session, +int cmd_register_consumer(const ltt_session::locked_ref& session, enum lttng_domain_type domain, const char *sock_path, struct consumer_data *cdata); -int cmd_set_consumer_uri(struct ltt_session *session, size_t nb_uri, struct lttng_uri *uris); -int cmd_setup_relayd(struct ltt_session *session); +int cmd_set_consumer_uri(const ltt_session::locked_ref& session, + size_t nb_uri, + struct lttng_uri *uris); +int cmd_setup_relayd(const ltt_session::locked_ref& session); /* Listing commands */ -ssize_t cmd_list_domains(struct ltt_session *session, struct lttng_domain **domains); +ssize_t cmd_list_domains(const ltt_session::locked_ref& session, struct lttng_domain **domains); enum lttng_error_code cmd_list_events(enum lttng_domain_type domain, - struct ltt_session *session, + const ltt_session::locked_ref& session, char *channel_name, struct lttng_payload *payload); enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain, - struct ltt_session *session, + const ltt_session::locked_ref& session, struct lttng_payload *payload); -void cmd_list_lttng_sessions(struct lttng_session *sessions, - size_t session_count, - uid_t uid, - gid_t gid); +void cmd_list_lttng_sessions(lttng_session *sessions, size_t session_count, uid_t uid, gid_t gid); enum lttng_error_code cmd_list_tracepoint_fields(enum lttng_domain_type domain, struct lttng_payload *reply); enum lttng_error_code cmd_list_tracepoints(enum lttng_domain_type domain, struct lttng_payload *reply_payload); -ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, +ssize_t cmd_snapshot_list_outputs(const ltt_session::locked_ref& session, struct lttng_snapshot_output **outputs); enum lttng_error_code cmd_list_syscalls(struct lttng_payload *reply_payload); -int cmd_data_pending(struct ltt_session *session); +int cmd_data_pending(const ltt_session::locked_ref& session); enum lttng_error_code cmd_kernel_tracer_status(enum lttng_kernel_tracer_status *status); /* Snapshot */ -int cmd_snapshot_add_output(struct ltt_session *session, +int cmd_snapshot_add_output(const ltt_session::locked_ref& session, const struct lttng_snapshot_output *output, uint32_t *id); -int cmd_snapshot_del_output(struct ltt_session *session, +int cmd_snapshot_del_output(const ltt_session::locked_ref& session, const struct lttng_snapshot_output *output); -int cmd_snapshot_record(struct ltt_session *session, +int cmd_snapshot_record(const ltt_session::locked_ref& session, const struct lttng_snapshot_output *output, int wait); -int cmd_set_session_shm_path(struct ltt_session *session, const char *shm_path); -int cmd_regenerate_metadata(struct ltt_session *session); -int cmd_regenerate_statedump(struct ltt_session *session); +int cmd_set_session_shm_path(const ltt_session::locked_ref& session, const char *shm_path); +int cmd_regenerate_metadata(const ltt_session::locked_ref& session); +int cmd_regenerate_statedump(const ltt_session::locked_ref& session); lttng::ctl::trigger cmd_register_trigger(const struct lttng_credentials *cmd_creds, @@ -177,14 +177,14 @@ cmd_execute_error_query(const struct lttng_credentials *cmd_creds, struct lttng_error_query_results **_results, struct notification_thread_handle *notification_thread); -int cmd_rotate_session(struct ltt_session *session, +int cmd_rotate_session(const ltt_session::locked_ref& session, struct lttng_rotate_session_return *rotate_return, bool quiet_rotation, enum lttng_trace_chunk_command_type command); -int cmd_rotate_get_info(struct ltt_session *session, +int cmd_rotate_get_info(const ltt_session::locked_ref& session, struct lttng_rotation_get_info_return *info_return, uint64_t rotate_id); -int cmd_rotation_set_schedule(struct ltt_session *session, +int cmd_rotation_set_schedule(const ltt_session::locked_ref& session, bool activate, enum lttng_rotation_schedule_type schedule_type, uint64_t value); diff --git a/src/bin/lttng-sessiond/consumer-destination-type.hpp b/src/bin/lttng-sessiond/consumer-destination-type.hpp new file mode 100644 index 000000000..3b020e19c --- /dev/null +++ b/src/bin/lttng-sessiond/consumer-destination-type.hpp @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2024 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_CONSUMER_DESTINATION_TYPE_HPP +#define LTTNG_CONSUMER_DESTINATION_TYPE_HPP + +enum consumer_dst_type { + CONSUMER_DST_LOCAL, + CONSUMER_DST_NET, +}; + +#endif /* LTTNG_CONSUMER_DESTINATION_TYPE_HPP */ diff --git a/src/bin/lttng-sessiond/consumer-output.hpp b/src/bin/lttng-sessiond/consumer-output.hpp new file mode 100644 index 000000000..1e1cbcb17 --- /dev/null +++ b/src/bin/lttng-sessiond/consumer-output.hpp @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2024 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_CONSUMER_OUTPUT_HPP +#define LTTNG_CONSUMER_OUTPUT_HPP + +#include "session.hpp" + +int consumer_set_network_uri(const ltt_session::locked_ref& session, + struct consumer_output *obj, + struct lttng_uri *uri); + +#endif /* LTTNG_CONSUMER_OUTPUT_HPP */ diff --git a/src/bin/lttng-sessiond/consumer.cpp b/src/bin/lttng-sessiond/consumer.cpp index 13c18325d..9e7e05363 100644 --- a/src/bin/lttng-sessiond/consumer.cpp +++ b/src/bin/lttng-sessiond/consumer.cpp @@ -7,6 +7,7 @@ */ #define _LGPL_SOURCE +#include "consumer-output.hpp" #include "consumer.hpp" #include "health-sessiond.hpp" #include "lttng-sessiond.hpp" @@ -674,7 +675,7 @@ error: * Return 0 on success. Return 1 if the URI were equal. Else, negative value on * error. */ -int consumer_set_network_uri(const struct ltt_session *session, +int consumer_set_network_uri(const ltt_session::locked_ref& session, struct consumer_output *output, struct lttng_uri *uri) { diff --git a/src/bin/lttng-sessiond/consumer.hpp b/src/bin/lttng-sessiond/consumer.hpp index 6c334875b..54365aa64 100644 --- a/src/bin/lttng-sessiond/consumer.hpp +++ b/src/bin/lttng-sessiond/consumer.hpp @@ -8,6 +8,7 @@ #ifndef _CONSUMER_H #define _CONSUMER_H +#include "consumer-destination-type.hpp" #include "snapshot.hpp" #include @@ -20,7 +21,6 @@ struct snapshot; struct snapshot_output; -struct ltt_session; /* * Needed until we use C++14, where std::max is constexpr. @@ -35,11 +35,6 @@ constexpr NumericalType max_constexpr(NumericalType l, NumericalType r) return l > r ? l : r; } -enum consumer_dst_type { - CONSUMER_DST_LOCAL, - CONSUMER_DST_NET, -}; - enum consumer_trace_chunk_exists_status { CONSUMER_TRACE_CHUNK_EXISTS_STATUS_EXISTS_LOCAL, CONSUMER_TRACE_CHUNK_EXISTS_STATUS_EXISTS_REMOTE, @@ -210,9 +205,7 @@ struct consumer_output *consumer_create_output(enum consumer_dst_type type); struct consumer_output *consumer_copy_output(struct consumer_output *obj); void consumer_output_get(struct consumer_output *obj); void consumer_output_put(struct consumer_output *obj); -int consumer_set_network_uri(const struct ltt_session *session, - struct consumer_output *obj, - struct lttng_uri *uri); + int consumer_send_fds(struct consumer_socket *sock, const int *fds, size_t nb_fd); int consumer_send_msg(struct consumer_socket *sock, const struct lttcomm_consumer_msg *msg); int consumer_send_stream(struct consumer_socket *sock, diff --git a/src/bin/lttng-sessiond/dispatch.cpp b/src/bin/lttng-sessiond/dispatch.cpp index 9d53896df..33e90a1a5 100644 --- a/src/bin/lttng-sessiond/dispatch.cpp +++ b/src/bin/lttng-sessiond/dispatch.cpp @@ -434,7 +434,6 @@ static void *thread_dispatch_ust_registration(void *data) err = 0; goto error; } - } } while (node != nullptr); diff --git a/src/bin/lttng-sessiond/kernel-consumer.cpp b/src/bin/lttng-sessiond/kernel-consumer.cpp index 1ea81f801..b813f0fe6 100644 --- a/src/bin/lttng-sessiond/kernel-consumer.cpp +++ b/src/bin/lttng-sessiond/kernel-consumer.cpp @@ -96,7 +96,6 @@ static int kernel_consumer_add_channel(struct consumer_socket *sock, bool is_local_trace; size_t consumer_path_offset = 0; lttng::urcu::read_lock_guard read_lock; - ltt_session::ref session; /* Safety net */ LTTNG_ASSERT(channel); @@ -168,7 +167,17 @@ static int kernel_consumer_add_channel(struct consumer_socket *sock, health_code_update(); try { - session = ltt_session::find_session(ksession->id); + const auto session = ltt_session::find_session(ksession->id); + + ASSERT_SESSION_LIST_LOCKED(); + + status = notification_thread_command_add_channel( + the_notification_thread_handle, + session->id, + channel->channel->name, + channel->key, + LTTNG_DOMAIN_KERNEL, + channel->channel->attr.subbuf_size * channel->channel->attr.num_subbuf); } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { ERR_FMT("Fatal error during the creation of a kernel channel: {}, location='{}'", ex.what(), @@ -176,16 +185,6 @@ static int kernel_consumer_add_channel(struct consumer_socket *sock, abort(); } - ASSERT_LOCKED(session->_lock); - ASSERT_SESSION_LIST_LOCKED(); - - status = notification_thread_command_add_channel(the_notification_thread_handle, - session->id, - channel->channel->name, - channel->key, - LTTNG_DOMAIN_KERNEL, - channel->channel->attr.subbuf_size * - channel->channel->attr.num_subbuf); if (status != LTTNG_OK) { ret = -1; goto error; diff --git a/src/bin/lttng-sessiond/kernel.cpp b/src/bin/lttng-sessiond/kernel.cpp index 4cc51a279..e7626a85d 100644 --- a/src/bin/lttng-sessiond/kernel.cpp +++ b/src/bin/lttng-sessiond/kernel.cpp @@ -163,13 +163,11 @@ error: * Create a new kernel session, register it to the kernel tracer and add it to * the session daemon session. */ -int kernel_create_session(struct ltt_session *session) +int kernel_create_session(const ltt_session::locked_ref& session) { int ret; struct ltt_kernel_session *lks; - LTTNG_ASSERT(session); - /* Allocate data structure */ lks = trace_kernel_create_session(); if (lks == nullptr) { @@ -1898,7 +1896,7 @@ int kernel_supports_event_notifiers() * * Return LTTNG_OK on success or else an LTTng error code. */ -enum lttng_error_code kernel_rotate_session(struct ltt_session *session) +enum lttng_error_code kernel_rotate_session(const ltt_session::locked_ref& session) { int ret; enum lttng_error_code status = LTTNG_OK; @@ -2243,7 +2241,7 @@ bool kernel_tracer_is_initialized() * * Return LTTNG_OK on success or else an LTTng error code. */ -enum lttng_error_code kernel_clear_session(struct ltt_session *session) +enum lttng_error_code kernel_clear_session(const ltt_session::locked_ref& session) { int ret; enum lttng_error_code status = LTTNG_OK; diff --git a/src/bin/lttng-sessiond/kernel.hpp b/src/bin/lttng-sessiond/kernel.hpp index 6cb89a19f..65b3c7896 100644 --- a/src/bin/lttng-sessiond/kernel.hpp +++ b/src/bin/lttng-sessiond/kernel.hpp @@ -24,7 +24,7 @@ #define KERNEL_EVENT_INIT_LIST_SIZE 64 int kernel_add_channel_context(struct ltt_kernel_channel *chan, struct ltt_kernel_context *ctx); -int kernel_create_session(struct ltt_session *session); +int kernel_create_session(const ltt_session::locked_ref& session); int kernel_create_channel(struct ltt_kernel_session *session, struct lttng_channel *chan); int kernel_create_event(struct lttng_event *ev, struct ltt_kernel_channel *channel, @@ -67,8 +67,8 @@ enum lttng_error_code kernel_snapshot_record(struct ltt_kernel_session *ksess, const struct consumer_output *output, uint64_t nb_packets_per_stream); int kernel_syscall_mask(int chan_fd, char **syscall_mask, uint32_t *nr_bits); -enum lttng_error_code kernel_rotate_session(struct ltt_session *session); -enum lttng_error_code kernel_clear_session(struct ltt_session *session); +enum lttng_error_code kernel_rotate_session(const ltt_session::locked_ref& session); +enum lttng_error_code kernel_clear_session(const ltt_session::locked_ref& session); int init_kernel_workarounds(); int kernel_supports_ring_buffer_snapshot_sample_positions(); diff --git a/src/bin/lttng-sessiond/main.cpp b/src/bin/lttng-sessiond/main.cpp index 6451899cd..ee4e4690b 100644 --- a/src/bin/lttng-sessiond/main.cpp +++ b/src/bin/lttng-sessiond/main.cpp @@ -1279,7 +1279,7 @@ end: static void destroy_all_sessions_and_wait() { - struct ltt_session *session, *tmp; + struct ltt_session *raw_session_ptr, *tmp; struct ltt_session_list *session_list; DBG("Initiating destruction of all sessions"); @@ -1292,20 +1292,19 @@ static void destroy_all_sessions_and_wait() } /* Initiate the destruction of all sessions. */ - cds_list_for_each_entry_safe (session, tmp, &session_list->head, list) { - if (!session_get(session)) { - continue; - } + cds_list_for_each_entry_safe (raw_session_ptr, tmp, &session_list->head, list) { + const auto session = [raw_session_ptr]() { + session_get(raw_session_ptr); + raw_session_ptr->lock(); + return ltt_session::locked_ref(*raw_session_ptr); + }(); - session_lock(session); if (session->destroyed) { - goto unlock_session; + continue; } + (void) cmd_stop_trace(session); (void) cmd_destroy_session(session, nullptr); - unlock_session: - session_unlock(session); - session_put(session); } /* Wait for the destruction of all sessions to complete. */ diff --git a/src/bin/lttng-sessiond/rotation-thread.cpp b/src/bin/lttng-sessiond/rotation-thread.cpp index ca7237802..71f9bbcb5 100644 --- a/src/bin/lttng-sessiond/rotation-thread.cpp +++ b/src/bin/lttng-sessiond/rotation-thread.cpp @@ -112,7 +112,8 @@ end: return exists; } -void check_session_rotation_pending_on_consumers(ltt_session& session, bool& _rotation_completed) +void check_session_rotation_pending_on_consumers(const ltt_session::locked_ref& session, + bool& _rotation_completed) { int ret = 0; struct consumer_socket *socket; @@ -123,27 +124,27 @@ void check_session_rotation_pending_on_consumers(ltt_session& session, bool& _ro enum lttng_trace_chunk_status chunk_status; lttng::urcu::read_lock_guard read_lock; - LTTNG_ASSERT(session.chunk_being_archived); + LTTNG_ASSERT(session->chunk_being_archived); /* * Check for a local pending rotation on all consumers (32-bit * user space, 64-bit user space, and kernel). */ - if (!session.ust_session) { + if (!session->ust_session) { goto skip_ust; } cds_lfht_for_each_entry ( - session.ust_session->consumer->socks->ht, &iter, socket, node.node) { - relayd_id = session.ust_session->consumer->type == CONSUMER_DST_LOCAL ? + session->ust_session->consumer->socks->ht, &iter, socket, node.node) { + relayd_id = session->ust_session->consumer->type == CONSUMER_DST_LOCAL ? -1ULL : - session.ust_session->consumer->net_seq_index; + session->ust_session->consumer->net_seq_index; lttng::pthread::lock_guard socket_lock(*socket->lock); ret = consumer_trace_chunk_exists(socket, relayd_id, - session.id, - session.chunk_being_archived, + session->id, + session->chunk_being_archived, &exists_status); if (ret) { ERR("Error occurred while checking rotation status on consumer daemon"); @@ -157,22 +158,22 @@ void check_session_rotation_pending_on_consumers(ltt_session& session, bool& _ro } skip_ust: - if (!session.kernel_session) { + if (!session->kernel_session) { goto skip_kernel; } cds_lfht_for_each_entry ( - session.kernel_session->consumer->socks->ht, &iter, socket, node.node) { + session->kernel_session->consumer->socks->ht, &iter, socket, node.node) { lttng::pthread::lock_guard socket_lock(*socket->lock); - relayd_id = session.kernel_session->consumer->type == CONSUMER_DST_LOCAL ? + relayd_id = session->kernel_session->consumer->type == CONSUMER_DST_LOCAL ? -1ULL : - session.kernel_session->consumer->net_seq_index; + session->kernel_session->consumer->net_seq_index; ret = consumer_trace_chunk_exists(socket, relayd_id, - session.id, - session.chunk_being_archived, + session->id, + session->chunk_being_archived, &exists_status); if (ret) { ERR("Error occurred while checking rotation status on consumer daemon"); @@ -190,20 +191,20 @@ end: if (!chunk_exists_on_peer) { uint64_t chunk_being_archived_id; - chunk_status = lttng_trace_chunk_get_id(session.chunk_being_archived, + chunk_status = lttng_trace_chunk_get_id(session->chunk_being_archived, &chunk_being_archived_id); LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK); DBG("Rotation of trace archive %" PRIu64 " of session \"%s\" is complete on all consumers", chunk_being_archived_id, - session.name); + session->name); } _rotation_completed = !chunk_exists_on_peer; if (ret) { ret = session_reset_rotation_state(session, LTTNG_ROTATION_STATE_ERROR); if (ret) { - ERR("Failed to reset rotation state of session \"%s\"", session.name); + ERR("Failed to reset rotation state of session \"%s\"", session->name); } } } @@ -213,7 +214,7 @@ end: * Should only return non-zero in the event of a fatal error. Doing so will * shutdown the thread. */ -int check_session_rotation_pending(ltt_session& session, +int check_session_rotation_pending(const ltt_session::locked_ref& session, notification_thread_handle& notification_thread_handle) { int ret; @@ -223,17 +224,17 @@ int check_session_rotation_pending(ltt_session& session, const char *archived_chunk_name; uint64_t chunk_being_archived_id; - if (!session.chunk_being_archived) { + if (!session->chunk_being_archived) { ret = 0; goto end; } chunk_status = - lttng_trace_chunk_get_id(session.chunk_being_archived, &chunk_being_archived_id); + lttng_trace_chunk_get_id(session->chunk_being_archived, &chunk_being_archived_id); LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK); DBG("Checking for pending rotation on session \"%s\", trace archive %" PRIu64, - session.name, + session->name, chunk_being_archived_id); /* @@ -250,7 +251,7 @@ int check_session_rotation_pending(ltt_session& session, } check_session_rotation_pending_on_consumers(session, rotation_completed); - if (!rotation_completed || session.rotation_state == LTTNG_ROTATION_STATE_ERROR) { + if (!rotation_completed || session->rotation_state == LTTNG_ROTATION_STATE_ERROR) { goto check_ongoing_rotation; } @@ -259,41 +260,41 @@ int check_session_rotation_pending(ltt_session& session, * rotations can start now. */ chunk_status = lttng_trace_chunk_get_name( - session.chunk_being_archived, &archived_chunk_name, nullptr); + session->chunk_being_archived, &archived_chunk_name, nullptr); LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK); - free(session.last_archived_chunk_name); - session.last_archived_chunk_name = strdup(archived_chunk_name); - if (!session.last_archived_chunk_name) { + free(session->last_archived_chunk_name); + session->last_archived_chunk_name = strdup(archived_chunk_name); + if (!session->last_archived_chunk_name) { PERROR("Failed to duplicate archived chunk name"); } session_reset_rotation_state(session, LTTNG_ROTATION_STATE_COMPLETED); - if (!session.quiet_rotation) { - location = session_get_trace_archive_location(&session); + if (!session->quiet_rotation) { + location = session_get_trace_archive_location(session); ret = notification_thread_command_session_rotation_completed( ¬ification_thread_handle, - session.id, - session.last_archived_chunk_id.value, + session->id, + session->last_archived_chunk_id.value, location); lttng_trace_archive_location_put(location); if (ret != LTTNG_OK) { ERR("Failed to notify notification thread of completed rotation for session %s", - session.name); + session->name); } } ret = 0; check_ongoing_rotation: - if (session.rotation_state == LTTNG_ROTATION_STATE_ONGOING) { - chunk_status = lttng_trace_chunk_get_id(session.chunk_being_archived, + if (session->rotation_state == LTTNG_ROTATION_STATE_ONGOING) { + chunk_status = lttng_trace_chunk_get_id(session->chunk_being_archived, &chunk_being_archived_id); LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK); DBG("Rotation of trace archive %" PRIu64 " is still pending for session %s", chunk_being_archived_id, - session.name); - ret = timer_session_rotation_pending_check_start(&session, + session->name); + ret = timer_session_rotation_pending_check_start(session, DEFAULT_ROTATE_PENDING_TIMER); if (ret) { ERR("Failed to re-enable rotation pending timer"); @@ -307,42 +308,46 @@ end: } /* Call with the session and session_list locks held. */ -int launch_session_rotation(ltt_session& session) +void launch_session_rotation(const ltt_session::locked_ref& session) { int ret; - struct lttng_rotate_session_return rotation_return; - DBG("Launching scheduled time-based rotation on session \"%s\"", session.name); + DBG_FMT("Launching scheduled time-based rotation: session_name='{}'", session->name); ASSERT_SESSION_LIST_LOCKED(); - ASSERT_LOCKED(session._lock); - ret = cmd_rotate_session(&session, - &rotation_return, - false, - LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED); - if (ret == LTTNG_OK) { - DBG("Scheduled time-based rotation successfully launched on session \"%s\"", - session.name); + ret = cmd_rotate_session( + session, nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED); + if (ret != LTTNG_OK) { + LTTNG_THROW_CTL(fmt::format("Failed to launch session rotation: session_name={}", + session->name), + static_cast(ret)); } else { /* Don't consider errors as fatal. */ - DBG("Scheduled time-based rotation aborted for session %s: %s", - session.name, - lttng_strerror(ret)); + DBG_FMT("Scheduled time-based rotation aborted session_name=`{}`, error='{}'", + session->name, + lttng_strerror(ret)); } - - return 0; } int run_job(const rotation_thread_job& job, - ltt_session& session, + const ltt_session::locked_ref& session, notification_thread_handle& notification_thread_handle) { - int ret; + int ret = 0; switch (job.type) { case ls::rotation_thread_job_type::SCHEDULED_ROTATION: - ret = launch_session_rotation(session); + try { + launch_session_rotation(session); + DBG("Scheduled time-based rotation successfully launched on session \"%s\"", + session->name); + } catch (const lttng::ctl::error& ctl_ex) { + /* Don't consider errors as fatal. */ + DBG("Scheduled time-based rotation aborted for session %s: %s", + session->name, + lttng_strerror(ctl_ex.code())); + } break; case ls::rotation_thread_job_type::CHECK_PENDING_ROTATION: ret = check_session_rotation_pending(session, notification_thread_handle); @@ -543,9 +548,9 @@ void ls::rotation_thread::_handle_job_queue() /* locked_ref will unlock the session and release the ref held by the job. */ session_lock(job->session); - auto session = ltt_session::locked_ref(job->session); + auto session = ltt_session::locked_ref(*job->session); - if (run_job(*job, *session, _notification_thread_handle)) { + if (run_job(*job, session, _notification_thread_handle)) { return; } } @@ -591,9 +596,39 @@ void ls::rotation_thread::_handle_notification(const lttng_notification& notific * sessions. */ const auto list_lock = lttng::sessiond::lock_session_list(); - ltt_session::locked_ref session; try { - session = ltt_session::find_locked_session(condition_session_name); + const auto session = ltt_session::find_locked_session(condition_session_name); + + if (!lttng_trigger_is_equal(session->rotate_trigger, + lttng_notification_get_const_trigger(¬ification))) { + DBG("Notification does not originate from the internal size-based scheduled rotation trigger, skipping"); + return; + } + + unsubscribe_session_consumed_size_rotation(*session); + + ret = cmd_rotate_session( + session, nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED); + if (ret != LTTNG_OK) { + switch (ret) { + case LTTNG_OK: + break; + case -LTTNG_ERR_ROTATION_PENDING: + DBG("Rotate already pending, subscribe to the next threshold value"); + break; + case -LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP: + DBG("Rotation already happened since last stop, subscribe to the next threshold value"); + break; + case -LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR: + DBG("Rotation already happened since last stop and clear, subscribe to the next threshold value"); + break; + default: + LTTNG_THROW_CTL("Failed to rotate on consumed size notification", + static_cast(-ret)); + } + } + + subscribe_session_consumed_size_rotation(*session, consumed + session->rotate_size); } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { DBG_FMT("Failed to find session while handling notification: notification_type={}, session name=`{}`", lttng_condition_type_str(condition_type), @@ -604,35 +639,6 @@ void ls::rotation_thread::_handle_notification(const lttng_notification& notific */ return; } - - if (!lttng_trigger_is_equal(session->rotate_trigger, - lttng_notification_get_const_trigger(¬ification))) { - DBG("Notification does not originate from the internal size-based scheduled rotation trigger, skipping"); - return; - } - - unsubscribe_session_consumed_size_rotation(*session); - - ret = cmd_rotate_session( - session.get(), nullptr, false, LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED); - switch (ret) { - case LTTNG_OK: - break; - case -LTTNG_ERR_ROTATION_PENDING: - DBG("Rotate already pending, subscribe to the next threshold value"); - break; - case -LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP: - DBG("Rotation already happened since last stop, subscribe to the next threshold value"); - break; - case -LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR: - DBG("Rotation already happened since last stop and clear, subscribe to the next threshold value"); - break; - default: - LTTNG_THROW_CTL("Failed to rotate on consumed size notification", - static_cast(-ret)); - } - - subscribe_session_consumed_size_rotation(*session, consumed + session->rotate_size); } void ls::rotation_thread::_handle_notification_channel_activity() diff --git a/src/bin/lttng-sessiond/save.cpp b/src/bin/lttng-sessiond/save.cpp index 484bf7c90..b65bcf9f2 100644 --- a/src/bin/lttng-sessiond/save.cpp +++ b/src/bin/lttng-sessiond/save.cpp @@ -1670,13 +1670,12 @@ end: } /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ -static int save_kernel_session(struct config_writer *writer, struct ltt_session *session) +static int save_kernel_session(struct config_writer *writer, const ltt_session::locked_ref& session) { int ret; struct ltt_kernel_channel *kchan; LTTNG_ASSERT(writer); - LTTNG_ASSERT(session); ret = config_writer_write_element_string( writer, config_element_type, config_domain_type_kernel); @@ -1746,7 +1745,7 @@ static const char *get_config_domain_str(enum lttng_domain_type domain) /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_process_attr_tracker(struct config_writer *writer, - struct ltt_session *sess, + const ltt_session::locked_ref& session, int domain, enum lttng_process_attr process_attr) { @@ -1795,13 +1794,13 @@ static int save_process_attr_tracker(struct config_writer *writer, switch (domain) { case LTTNG_DOMAIN_KERNEL: { - tracker = kernel_get_process_attr_tracker(sess->kernel_session, process_attr); + tracker = kernel_get_process_attr_tracker(session->kernel_session, process_attr); LTTNG_ASSERT(tracker); break; } case LTTNG_DOMAIN_UST: { - tracker = trace_ust_get_process_attr_tracker(sess->ust_session, process_attr); + tracker = trace_ust_get_process_attr_tracker(session->ust_session, process_attr); LTTNG_ASSERT(tracker); break; } @@ -1922,55 +1921,58 @@ end: } /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ -static int -save_process_attr_trackers(struct config_writer *writer, struct ltt_session *sess, int domain) +static int save_process_attr_trackers(struct config_writer *writer, + const ltt_session::locked_ref& session, + int domain) { int ret; switch (domain) { case LTTNG_DOMAIN_KERNEL: ret = save_process_attr_tracker( - writer, sess, domain, LTTNG_PROCESS_ATTR_PROCESS_ID); + writer, session, domain, LTTNG_PROCESS_ATTR_PROCESS_ID); if (ret != LTTNG_OK) { goto end; } ret = save_process_attr_tracker( - writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); + writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); if (ret != LTTNG_OK) { goto end; } - ret = save_process_attr_tracker(writer, sess, domain, LTTNG_PROCESS_ATTR_USER_ID); + ret = save_process_attr_tracker( + writer, session, domain, LTTNG_PROCESS_ATTR_USER_ID); if (ret != LTTNG_OK) { goto end; } ret = save_process_attr_tracker( - writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); + writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); if (ret != LTTNG_OK) { goto end; } - ret = save_process_attr_tracker(writer, sess, domain, LTTNG_PROCESS_ATTR_GROUP_ID); + ret = save_process_attr_tracker( + writer, session, domain, LTTNG_PROCESS_ATTR_GROUP_ID); if (ret != LTTNG_OK) { goto end; } ret = save_process_attr_tracker( - writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); + writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); if (ret != LTTNG_OK) { goto end; } break; case LTTNG_DOMAIN_UST: ret = save_process_attr_tracker( - writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); + writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); if (ret != LTTNG_OK) { goto end; } ret = save_process_attr_tracker( - writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); + writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); if (ret != LTTNG_OK) { goto end; } ret = save_process_attr_tracker( - writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); + writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); if (ret != LTTNG_OK) { goto end; } @@ -1986,7 +1988,7 @@ end: /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_ust_domain(struct config_writer *writer, - struct ltt_session *session, + const ltt_session::locked_ref& session, enum lttng_domain_type domain) { int ret; @@ -1997,7 +1999,6 @@ static int save_ust_domain(struct config_writer *writer, const char *config_domain_name; LTTNG_ASSERT(writer); - LTTNG_ASSERT(session); ret = config_writer_open_element(writer, config_element_domain); if (ret) { @@ -2092,12 +2093,11 @@ end: } /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ -static int save_domains(struct config_writer *writer, struct ltt_session *session) +static int save_domains(struct config_writer *writer, const ltt_session::locked_ref& session) { int ret = LTTNG_OK; LTTNG_ASSERT(writer); - LTTNG_ASSERT(session); if (!session->kernel_session && !session->ust_session) { goto end; @@ -2371,12 +2371,11 @@ end_unlock: } /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ -static int save_session_output(struct config_writer *writer, struct ltt_session *session) +static int save_session_output(struct config_writer *writer, const ltt_session::locked_ref& session) { int ret; LTTNG_ASSERT(writer); - LTTNG_ASSERT(session); if ((session->snapshot_mode && session->snapshot.nb_output == 0) || (!session->snapshot_mode && !session->consumer)) { @@ -2458,7 +2457,7 @@ end: } static int save_session_rotation_schedules(struct config_writer *writer, - struct ltt_session *session) + const ltt_session::locked_ref& session) { int ret; @@ -2497,7 +2496,7 @@ end: * * Return LTTNG_OK on success else a LTTNG_ERR* code. */ -static int save_session(struct ltt_session *session, +static int save_session(const ltt_session::locked_ref& session, struct lttng_save_session_attr *attr, lttng_sock_cred *creds) { @@ -2509,7 +2508,6 @@ static int save_session(struct ltt_session *session, const char *provided_path; int file_open_flags = O_CREAT | O_WRONLY | O_TRUNC; - LTTNG_ASSERT(session); LTTNG_ASSERT(attr); LTTNG_ASSERT(creds); @@ -2735,50 +2733,42 @@ end: int cmd_save_sessions(struct lttng_save_session_attr *attr, lttng_sock_cred *creds) { - int ret; - const char *session_name; - const auto list_lock = lttng::sessiond::lock_session_list(); + const auto session_name = lttng_save_session_attr_get_session_name(attr); - session_name = lttng_save_session_attr_get_session_name(attr); if (session_name) { - /* - * Mind the order of the declaration of list_lock vs session: - * the session list lock must always be released _after_ the release of - * a session's reference (the destruction of a ref/locked_ref) to ensure - * since the reference's release may unpublish the session from the list of - * sessions. - */ - ltt_session::locked_ref session; - + * Mind the order of the declaration of list_lock vs session: + * the session list lock must always be released _after_ the release of + * a session's reference (the destruction of a ref/locked_ref) to ensure + * since the reference's release may unpublish the session from the list of + * sessions. + */ try { - session = ltt_session::find_locked_session(session_name); + const auto session = ltt_session::find_locked_session(session_name); + const auto save_ret = save_session(session, attr, creds); + if (save_ret != LTTNG_OK) { + return save_ret; + } } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { WARN_FMT("Failed to save session: {} {}", ex.what(), ex.source_location); - ret = LTTNG_ERR_SESS_NOT_FOUND; - return ret; - } - - ret = save_session(session.get(), attr, creds); - if (ret != LTTNG_OK) { - return ret; + return LTTNG_ERR_SESS_NOT_FOUND; } } else { struct ltt_session_list *list = session_get_list(); - struct ltt_session *session; + struct ltt_session *raw_session_ptr; + + cds_list_for_each_entry (raw_session_ptr, &list->head, list) { + auto session = [raw_session_ptr]() { + session_get(raw_session_ptr); + raw_session_ptr->lock(); + return ltt_session::locked_ref(*raw_session_ptr); + }(); + const auto save_ret = save_session(session, attr, creds); - cds_list_for_each_entry (session, &list->head, list) { - if (!session_get(session)) { - continue; - } - session_lock(session); - ret = save_session(session, attr, creds); - session_unlock(session); - session_put(session); /* Don't abort if we don't have the required permissions. */ - if (ret != LTTNG_OK && ret != LTTNG_ERR_EPERM) { - return ret; + if (save_ret != LTTNG_OK && save_ret != LTTNG_ERR_EPERM) { + return save_ret; } } } diff --git a/src/bin/lttng-sessiond/session.cpp b/src/bin/lttng-sessiond/session.cpp index b588e6055..97391ad98 100644 --- a/src/bin/lttng-sessiond/session.cpp +++ b/src/bin/lttng-sessiond/session.cpp @@ -218,10 +218,8 @@ int session_trylock_list() noexcept /* * Get the session's consumer destination type. - * - * The caller must hold the session lock. */ -enum consumer_dst_type session_get_consumer_destination_type(const struct ltt_session *session) +enum consumer_dst_type session_get_consumer_destination_type(const ltt_session::locked_ref& session) { /* * The output information is duplicated in both of those session types. @@ -235,10 +233,8 @@ enum consumer_dst_type session_get_consumer_destination_type(const struct ltt_se /* * Get the session's consumer network hostname. * The caller must ensure that the destination is of type "net". - * - * The caller must hold the session lock. */ -const char *session_get_net_consumer_hostname(const struct ltt_session *session) +const char *session_get_net_consumer_hostname(const ltt_session::locked_ref& session) { const char *hostname = nullptr; const struct consumer_output *output; @@ -266,10 +262,8 @@ const char *session_get_net_consumer_hostname(const struct ltt_session *session) /* * Get the session's consumer network control and data ports. * The caller must ensure that the destination is of type "net". - * - * The caller must hold the session lock. */ -void session_get_net_consumer_ports(const struct ltt_session *session, +void session_get_net_consumer_ports(const ltt_session::locked_ref& session, uint16_t *control_port, uint16_t *data_port) { @@ -283,11 +277,9 @@ void session_get_net_consumer_ports(const struct ltt_session *session, /* * Get the location of the latest trace archive produced by a rotation. - * - * The caller must hold the session lock. */ struct lttng_trace_archive_location * -session_get_trace_archive_location(const struct ltt_session *session) +session_get_trace_archive_location(const ltt_session::locked_ref& session) { int ret; struct lttng_trace_archive_location *location = nullptr; @@ -508,12 +500,12 @@ void session_unlock(struct ltt_session *session) session->unlock(); } -void ltt_session::_const_session_unlock(const ltt_session &session) +void ltt_session::_const_session_unlock(const ltt_session& session) { pthread_mutex_unlock(&session._lock); } -static int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, +static int _session_set_trace_chunk_no_lock_check(const ltt_session::locked_ref& session, struct lttng_trace_chunk *new_trace_chunk, struct lttng_trace_chunk **_current_trace_chunk) { @@ -652,7 +644,7 @@ error: } struct lttng_trace_chunk * -session_create_new_trace_chunk(const struct ltt_session *session, +session_create_new_trace_chunk(const ltt_session::locked_ref& session, const struct consumer_output *consumer_output_override, const char *session_base_path_override, const char *chunk_name_override) @@ -759,7 +751,7 @@ error: goto end; } -int session_close_trace_chunk(struct ltt_session *session, +int session_close_trace_chunk(const ltt_session::locked_ref& session, struct lttng_trace_chunk *trace_chunk, enum lttng_trace_chunk_command_type close_command, char *closed_trace_chunk_path) @@ -886,7 +878,7 @@ end: * daemon as the same "offset" in a metadata stream will no longer point * to the same content. */ -static enum lttng_error_code session_kernel_open_packets(struct ltt_session *session) +static enum lttng_error_code session_kernel_open_packets(const ltt_session::locked_ref& session) { enum lttng_error_code ret = LTTNG_OK; struct consumer_socket *socket; @@ -921,7 +913,7 @@ end: return ret; } -enum lttng_error_code session_open_packets(struct ltt_session *session) +enum lttng_error_code session_open_packets(const ltt_session::locked_ref& session) { enum lttng_error_code ret = LTTNG_OK; @@ -952,7 +944,7 @@ end: * * Must be called with the session lock held. */ -int session_set_trace_chunk(struct ltt_session *session, +int session_set_trace_chunk(const ltt_session::locked_ref& session, struct lttng_trace_chunk *new_trace_chunk, struct lttng_trace_chunk **current_trace_chunk) { @@ -961,10 +953,10 @@ int session_set_trace_chunk(struct ltt_session *session, session, new_trace_chunk, current_trace_chunk); } -static void session_notify_destruction(const struct ltt_session *session) +static void session_notify_destruction(const ltt_session::locked_ref& session) { size_t i; - const size_t count = lttng_dynamic_array_get_count(&session->destroy_notifiers); + const auto count = lttng_dynamic_array_get_count(&session->destroy_notifiers); for (i = 0; i < count; i++) { const struct ltt_session_destroy_notifier_element *element = @@ -978,19 +970,19 @@ static void session_notify_destruction(const struct ltt_session *session) /* * Fire each clear notifier once, and remove them from the array. */ -void session_notify_clear(ltt_session& session) +void session_notify_clear(const ltt_session::locked_ref& session) { size_t i; - const size_t count = lttng_dynamic_array_get_count(&session.clear_notifiers); + const auto count = lttng_dynamic_array_get_count(&session->clear_notifiers); for (i = 0; i < count; i++) { const struct ltt_session_clear_notifier_element *element = (ltt_session_clear_notifier_element *) lttng_dynamic_array_get_element( - &session.clear_notifiers, i); + &session->clear_notifiers, i); - element->notifier(&session, element->user_data); + element->notifier(session, element->user_data); } - lttng_dynamic_array_clear(&session.clear_notifiers); + lttng_dynamic_array_clear(&session->clear_notifiers); } static void session_release(struct urcu_ref *ref) @@ -1037,14 +1029,26 @@ static void session_release(struct urcu_ref *ref) snapshot_destroy(&session->snapshot); - pthread_mutex_destroy(&session->_lock); - if (session_published) { ASSERT_SESSION_LIST_LOCKED(); del_session_list(session); del_session_ht(session); } - session_notify_destruction(session); + + /* + * The notifiers make use of free-functions that expect a locked reference to a session. + * To create such a reference, we need to acquire the lock and acquire a reference (increase + * the ref-count). To ensure the release of the reference does not re-cross the zero value, + * set the refcount to a tombstone value. + */ + session->ref_count.refcount = 0xDEAD5E55; + session_notify_destruction([session]() { + session_lock(session); + session_get(session); + return ltt_session::locked_ref(*session); + }()); + + pthread_mutex_destroy(&session->_lock); consumer_output_put(session->consumer); kernel_free_session(ksess); @@ -1129,7 +1133,7 @@ void session_destroy(struct ltt_session *session) session_put(session); } -int session_add_destroy_notifier(struct ltt_session *session, +int session_add_destroy_notifier(const ltt_session::locked_ref& session, ltt_session_destroy_notifier notifier, void *user_data) { @@ -1139,7 +1143,7 @@ int session_add_destroy_notifier(struct ltt_session *session, return lttng_dynamic_array_add_element(&session->destroy_notifiers, &element); } -int session_add_clear_notifier(struct ltt_session *session, +int session_add_clear_notifier(const ltt_session::locked_ref& session, ltt_session_clear_notifier notifier, void *user_data) { @@ -1330,9 +1334,8 @@ error: * Check if the UID matches the session. Root user has access to all * sessions. */ -bool session_access_ok(struct ltt_session *session, uid_t uid) +bool session_access_ok(const ltt_session::locked_ref& session, uid_t uid) { - LTTNG_ASSERT(session); return (uid == session->uid) || uid == 0; } @@ -1351,26 +1354,26 @@ bool session_access_ok(struct ltt_session *session, uid_t uid) * * Must be called with the session and session_list locks held. */ -int session_reset_rotation_state(ltt_session& session, enum lttng_rotation_state result) +int session_reset_rotation_state(const ltt_session::locked_ref& session, + enum lttng_rotation_state result) { int ret = 0; ASSERT_SESSION_LIST_LOCKED(); - ASSERT_LOCKED(session._lock); - session.rotation_state = result; - if (session.rotation_pending_check_timer_enabled) { + session->rotation_state = result; + if (session->rotation_pending_check_timer_enabled) { ret = timer_session_rotation_pending_check_stop(session); } - if (session.chunk_being_archived) { + if (session->chunk_being_archived) { uint64_t chunk_id; enum lttng_trace_chunk_status chunk_status; - chunk_status = lttng_trace_chunk_get_id(session.chunk_being_archived, &chunk_id); + chunk_status = lttng_trace_chunk_get_id(session->chunk_being_archived, &chunk_id); LTTNG_ASSERT(chunk_status == LTTNG_TRACE_CHUNK_STATUS_OK); - LTTNG_OPTIONAL_SET(&session.last_archived_chunk_id, chunk_id); - lttng_trace_chunk_put(session.chunk_being_archived); - session.chunk_being_archived = nullptr; + LTTNG_OPTIONAL_SET(&session->last_archived_chunk_id, chunk_id); + lttng_trace_chunk_put(session->chunk_being_archived); + session->chunk_being_archived = nullptr; /* * Fire the clear reply notifiers if we are completing a clear * rotation. @@ -1453,7 +1456,7 @@ ltt_session::locked_ref ltt_session::find_locked_session(ltt_session::id_t id) * session. */ session_lock(session); - return ltt_session::locked_ref(session); + return ltt_session::locked_ref(*session); } ltt_session::locked_ref ltt_session::find_locked_session(lttng::c_string_view name) @@ -1466,7 +1469,7 @@ ltt_session::locked_ref ltt_session::find_locked_session(lttng::c_string_view na } session_lock(session); - return ltt_session::locked_ref(session); + return ltt_session::locked_ref(*session); } ltt_session::const_locked_ref ltt_session::find_locked_const_session(ltt_session::id_t id) @@ -1479,7 +1482,7 @@ ltt_session::const_locked_ref ltt_session::find_locked_const_session(ltt_session } session_lock(session); - return ltt_session::const_locked_ref(session); + return ltt_session::const_locked_ref(*session); } ltt_session::const_locked_ref ltt_session::find_locked_const_session(lttng::c_string_view name) @@ -1492,7 +1495,7 @@ ltt_session::const_locked_ref ltt_session::find_locked_const_session(lttng::c_st } session_lock(session); - return ltt_session::const_locked_ref(session); + return ltt_session::const_locked_ref(*session); } ltt_session::ref ltt_session::find_session(ltt_session::id_t id) @@ -1504,7 +1507,7 @@ ltt_session::ref ltt_session::find_session(ltt_session::id_t id) LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id); } - return ltt_session::ref(session); + return ltt_session::ref(*session); } ltt_session::ref ltt_session::find_session(lttng::c_string_view name) @@ -1516,7 +1519,7 @@ ltt_session::ref ltt_session::find_session(lttng::c_string_view name) LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data()); } - return ltt_session::ref(session); + return ltt_session::ref(*session); } ltt_session::const_ref ltt_session::find_const_session(ltt_session::id_t id) @@ -1528,7 +1531,7 @@ ltt_session::const_ref ltt_session::find_const_session(ltt_session::id_t id) LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id); } - return ltt_session::const_ref(session); + return ltt_session::const_ref(*session); } ltt_session::const_ref ltt_session::find_const_session(lttng::c_string_view name) @@ -1540,7 +1543,7 @@ ltt_session::const_ref ltt_session::find_const_session(lttng::c_string_view name LTTNG_THROW_SESSION_NOT_FOUND_BY_NAME_ERROR(name.data()); } - return ltt_session::const_ref(session); + return ltt_session::const_ref(*session); } void ltt_session::_const_session_put(const ltt_session *session) diff --git a/src/bin/lttng-sessiond/session.hpp b/src/bin/lttng-sessiond/session.hpp index e4d62a7c4..d86147ac4 100644 --- a/src/bin/lttng-sessiond/session.hpp +++ b/src/bin/lttng-sessiond/session.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -32,9 +33,6 @@ struct ltt_ust_session; -using ltt_session_destroy_notifier = void (*)(const struct ltt_session *, void *); -using ltt_session_clear_notifier = void (*)(const struct ltt_session *, void *); - struct ltt_session; struct ltt_session_list; @@ -63,75 +61,6 @@ int session_trylock_list() noexcept; #define LTTNG_THROW_SESSION_NOT_FOUND_BY_ID_ERROR(id) \ throw lttng::sessiond::exceptions::session_not_found_error(id, LTTNG_SOURCE_LOCATION()) -void session_destroy(struct ltt_session *session); -int session_add_destroy_notifier(struct ltt_session *session, - ltt_session_destroy_notifier notifier, - void *user_data); - -int session_add_clear_notifier(struct ltt_session *session, - ltt_session_clear_notifier notifier, - void *user_data); -void session_notify_clear(ltt_session& session); - -enum consumer_dst_type session_get_consumer_destination_type(const struct ltt_session *session); -const char *session_get_net_consumer_hostname(const struct ltt_session *session); -void session_get_net_consumer_ports(const struct ltt_session *session, - uint16_t *control_port, - uint16_t *data_port); -struct lttng_trace_archive_location * -session_get_trace_archive_location(const struct ltt_session *session); - -struct ltt_session_list *session_get_list(); -void session_list_wait_empty(std::unique_lock list_lock); - -bool session_access_ok(struct ltt_session *session, uid_t uid); - -int session_reset_rotation_state(ltt_session& session, enum lttng_rotation_state result); - -/* Create a new trace chunk object from the session's configuration. */ -struct lttng_trace_chunk * -session_create_new_trace_chunk(const struct ltt_session *session, - const struct consumer_output *consumer_output_override, - const char *session_base_path_override, - const char *chunk_name_override); - -/* - * Set `new_trace_chunk` as the session's current trace chunk. A reference - * to `new_trace_chunk` is acquired by the session. The chunk is created - * on remote peers (consumer and relay daemons). - * - * A reference to the session's current trace chunk is returned through - * `current_session_trace_chunk` on success. - */ -int session_set_trace_chunk(struct ltt_session *session, - struct lttng_trace_chunk *new_trace_chunk, - struct lttng_trace_chunk **current_session_trace_chunk); - -/* - * Close a chunk on the remote peers of a session. Has no effect on the - * ltt_session itself. - */ -int session_close_trace_chunk(struct ltt_session *session, - struct lttng_trace_chunk *trace_chunk, - enum lttng_trace_chunk_command_type close_command, - char *path); - -/* Open a packet in all channels of a given session. */ -enum lttng_error_code session_open_packets(struct ltt_session *session); - -bool session_output_supports_trace_chunks(const struct ltt_session *session); - -/* - * Sample the id of a session looked up via its name. - * Here the term "sampling" hint the caller that this return the id at a given - * point in time with no guarantee that the session for which the id was - * sampled still exist at that point. - * - * Return 0 when the session is not found, - * Return 1 when the session is found and set `id`. - */ -bool sample_session_id_by_name(const char *name, uint64_t *id); - /* * Tracing session list * @@ -174,25 +103,25 @@ private: static void _locked_session_release(ltt_session *session); static void _locked_const_session_release(const ltt_session *session); static void _const_session_put(const ltt_session *session); - static void _const_session_unlock(const ltt_session &session); + static void _const_session_unlock(const ltt_session& session); public: - using locked_ref = - std::unique_ptr::deleter>; - using ref = std::unique_ptr< + using locked_ref = lttng::non_copyable_reference< + ltt_session, + lttng::memory::create_deleter_class::deleter>; + using ref = lttng::non_copyable_reference< ltt_session, lttng::memory::create_deleter_class::deleter>; - using const_locked_ref = - std::unique_ptr::deleter>; - using const_ref = std::unique_ptr< + using const_locked_ref = lttng::non_copyable_reference< + const ltt_session, + lttng::memory::create_deleter_class< + const ltt_session, + ltt_session::_locked_const_session_release>::deleter>; + using const_ref = lttng::non_copyable_reference< const ltt_session, - lttng::memory::create_deleter_class::deleter>; + lttng::memory::create_deleter_class::deleter>; void lock() const noexcept; void unlock() const noexcept; @@ -343,10 +272,15 @@ public: struct lttng_dynamic_array clear_notifiers; /* Session base path override. Set non-null. */ char *base_path; - - }; +/* + * Destruction notifiers are invoked in an exclusive context. There is no need for the session to be + * locked nor for a reference to be acquired. + */ +using ltt_session_destroy_notifier = void (*)(const ltt_session::locked_ref&, void *); +using ltt_session_clear_notifier = void (*)(const ltt_session::locked_ref&, void *); + namespace lttng { namespace sessiond { @@ -376,7 +310,8 @@ public: } /* NOLINTEND(google-explicit-constructor) */ - explicit query_parameter(ltt_session::id_t id_) : type(query_type::BY_ID), parameter(id_) + explicit query_parameter(ltt_session::id_t id_) : + type(query_type::BY_ID), parameter(id_) { } @@ -453,4 +388,75 @@ public: } /* namespace sessiond */ } /* namespace lttng */ +void session_destroy(struct ltt_session *session); +int session_add_destroy_notifier(const ltt_session::locked_ref& session, + ltt_session_destroy_notifier notifier, + void *user_data); + +int session_add_clear_notifier(const ltt_session::locked_ref& session, + ltt_session_clear_notifier notifier, + void *user_data); +void session_notify_clear(const ltt_session::locked_ref& session); + +enum consumer_dst_type +session_get_consumer_destination_type(const ltt_session::locked_ref& session); +const char *session_get_net_consumer_hostname(const ltt_session::locked_ref& session); +void session_get_net_consumer_ports(const ltt_session::locked_ref& session, + uint16_t *control_port, + uint16_t *data_port); +struct lttng_trace_archive_location * +session_get_trace_archive_location(const ltt_session::locked_ref& session); + +struct ltt_session_list *session_get_list(); +void session_list_wait_empty(std::unique_lock list_lock); + +bool session_access_ok(const ltt_session::locked_ref& session, uid_t uid); + +int session_reset_rotation_state(const ltt_session::locked_ref& session, + enum lttng_rotation_state result); + +/* Create a new trace chunk object from the session's configuration. */ +struct lttng_trace_chunk * +session_create_new_trace_chunk(const ltt_session::locked_ref& session, + const struct consumer_output *consumer_output_override, + const char *session_base_path_override, + const char *chunk_name_override); + +/* + * Set `new_trace_chunk` as the session's current trace chunk. A reference + * to `new_trace_chunk` is acquired by the session. The chunk is created + * on remote peers (consumer and relay daemons). + * + * A reference to the session's current trace chunk is returned through + * `current_session_trace_chunk` on success. + */ +int session_set_trace_chunk(const ltt_session::locked_ref& session, + struct lttng_trace_chunk *new_trace_chunk, + struct lttng_trace_chunk **current_session_trace_chunk); + +/* + * Close a chunk on the remote peers of a session. Has no effect on the + * ltt_session itself. + */ +int session_close_trace_chunk(const ltt_session::locked_ref& session, + struct lttng_trace_chunk *trace_chunk, + enum lttng_trace_chunk_command_type close_command, + char *path); + +/* Open a packet in all channels of a given session. */ +enum lttng_error_code session_open_packets(const ltt_session::locked_ref& session); + +bool session_output_supports_trace_chunks(const struct ltt_session *session); + +/* + * Sample the id of a session looked up via its name. + * Here the term "sampling" hint the caller that this return the id at a given + * point in time with no guarantee that the session for which the id was + * sampled still exist at that point. + * + * Return 0 when the session is not found, + * Return 1 when the session is found and set `id`. + */ +bool sample_session_id_by_name(const char *name, uint64_t *id); + #endif /* _LTT_SESSION_H */ diff --git a/src/bin/lttng-sessiond/snapshot-output.hpp b/src/bin/lttng-sessiond/snapshot-output.hpp new file mode 100644 index 000000000..6d580e4ed --- /dev/null +++ b/src/bin/lttng-sessiond/snapshot-output.hpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_SNAPSHOT_OUTPUT_HPP +#define LTTNG_SNAPSHOT_OUTPUT_HPP + +int snapshot_output_init(const ltt_session::locked_ref& session, + uint64_t max_size, + const char *name, + const char *ctrl_url, + const char *data_url, + struct consumer_output *consumer, + struct snapshot_output *output, + struct snapshot *snapshot); +int snapshot_output_init_with_uri(const ltt_session::locked_ref& session, + uint64_t max_size, + const char *name, + struct lttng_uri *uris, + size_t nb_uri, + struct consumer_output *consumer, + struct snapshot_output *output, + struct snapshot *snapshot); + +#endif /* LTTNG_SNAPSHOT_OUTPUT_HPP */ diff --git a/src/bin/lttng-sessiond/snapshot.cpp b/src/bin/lttng-sessiond/snapshot.cpp index e7a003354..4f72306ac 100644 --- a/src/bin/lttng-sessiond/snapshot.cpp +++ b/src/bin/lttng-sessiond/snapshot.cpp @@ -6,6 +6,8 @@ */ #define _LGPL_SOURCE +#include "consumer-output.hpp" +#include "snapshot-output.hpp" #include "snapshot.hpp" #include "utils.hpp" @@ -29,7 +31,7 @@ static inline unsigned long get_next_output_id(struct snapshot *snapshot) * * Return 0 on success or else a negative value. */ -static int output_init(const struct ltt_session *session, +static int output_init(const ltt_session::locked_ref& session, uint64_t max_size, const char *name, struct lttng_uri *uris, @@ -130,7 +132,7 @@ end: * * Return 0 on success or else a negative value. */ -int snapshot_output_init_with_uri(const struct ltt_session *session, +int snapshot_output_init_with_uri(const ltt_session::locked_ref& session, uint64_t max_size, const char *name, struct lttng_uri *uris, @@ -148,7 +150,7 @@ int snapshot_output_init_with_uri(const struct ltt_session *session, * * Return 0 on success or else a negative value. */ -int snapshot_output_init(const struct ltt_session *session, +int snapshot_output_init(const ltt_session::locked_ref& session, uint64_t max_size, const char *name, const char *ctrl_url, diff --git a/src/bin/lttng-sessiond/snapshot.hpp b/src/bin/lttng-sessiond/snapshot.hpp index 726b89f80..bdc520643 100644 --- a/src/bin/lttng-sessiond/snapshot.hpp +++ b/src/bin/lttng-sessiond/snapshot.hpp @@ -18,7 +18,6 @@ #include struct consumer_output; -struct ltt_session; struct snapshot_output { uint32_t id; @@ -61,22 +60,7 @@ void snapshot_add_output(struct snapshot *snapshot, struct snapshot_output *outp /* Snapshot output object. */ struct snapshot_output *snapshot_output_alloc(); void snapshot_output_destroy(struct snapshot_output *obj); -int snapshot_output_init(const struct ltt_session *session, - uint64_t max_size, - const char *name, - const char *ctrl_url, - const char *data_url, - struct consumer_output *consumer, - struct snapshot_output *output, - struct snapshot *snapshot); -int snapshot_output_init_with_uri(const struct ltt_session *session, - uint64_t max_size, - const char *name, - struct lttng_uri *uris, - size_t nb_uri, - struct consumer_output *consumer, - struct snapshot_output *output, - struct snapshot *snapshot); + struct snapshot_output *snapshot_find_output_by_id(uint32_t id, struct snapshot *snapshot); struct snapshot_output *snapshot_find_output_by_name(const char *name, struct snapshot *snapshot); diff --git a/src/bin/lttng-sessiond/timer.cpp b/src/bin/lttng-sessiond/timer.cpp index 838983e3b..b70d64849 100644 --- a/src/bin/lttng-sessiond/timer.cpp +++ b/src/bin/lttng-sessiond/timer.cpp @@ -199,15 +199,16 @@ end: return ret; } -int timer_session_rotation_pending_check_start(struct ltt_session *session, +int timer_session_rotation_pending_check_start(const ltt_session::locked_ref& session, unsigned int interval_us) { int ret; - if (!session_get(session)) { + if (!session_get(&session.get())) { ret = -1; goto end; } + DBG("Enabling session rotation pending check timer on session %" PRIu64, session->id); /* * We arm this timer in a one-shot mode so we don't have to disable it @@ -219,7 +220,7 @@ int timer_session_rotation_pending_check_start(struct ltt_session *session, * no need to go through the whole signal teardown scheme everytime. */ ret = timer_start(&session->rotation_pending_check_timer, - session, + &session.get(), interval_us, LTTNG_SESSIOND_SIG_PENDING_ROTATION_CHECK, /* one-shot */ true); @@ -231,39 +232,39 @@ end: } /* - * Call with session and session_list locks held. + * Call with session_list lock held. */ -int timer_session_rotation_pending_check_stop(ltt_session& session) +int timer_session_rotation_pending_check_stop(const ltt_session::locked_ref& session) { int ret; - LTTNG_ASSERT(session.rotation_pending_check_timer_enabled); + LTTNG_ASSERT(session->rotation_pending_check_timer_enabled); - DBG("Disabling session rotation pending check timer on session %" PRIu64, session.id); - ret = timer_stop(&session.rotation_pending_check_timer, + DBG("Disabling session rotation pending check timer on session %" PRIu64, session->id); + ret = timer_stop(&session->rotation_pending_check_timer, LTTNG_SESSIOND_SIG_PENDING_ROTATION_CHECK); if (ret == -1) { ERR("Failed to stop rotate_pending_check timer"); } else { - session.rotation_pending_check_timer_enabled = false; + session->rotation_pending_check_timer_enabled = false; /* * The timer's reference to the session can be released safely. */ - session_put(&session); + session_put(&session.get()); } return ret; } /* - * Call with session and session_list locks held. + * Call with session_list lock held. */ -int timer_session_rotation_schedule_timer_start(struct ltt_session *session, +int timer_session_rotation_schedule_timer_start(const ltt_session::locked_ref& session, unsigned int interval_us) { int ret; - if (!session_get(session)) { + if (!session_get(&session.get())) { ret = -1; goto end; } @@ -272,7 +273,7 @@ int timer_session_rotation_schedule_timer_start(struct ltt_session *session, interval_us, USEC_UNIT); ret = timer_start(&session->rotation_schedule_timer, - session, + &session.get(), interval_us, LTTNG_SESSIOND_SIG_SCHEDULED_ROTATION, /* one-shot */ false); @@ -287,12 +288,10 @@ end: /* * Call with session and session_list locks held. */ -int timer_session_rotation_schedule_timer_stop(struct ltt_session *session) +int timer_session_rotation_schedule_timer_stop(const ltt_session::locked_ref& session) { int ret = 0; - LTTNG_ASSERT(session); - if (!session->rotation_schedule_timer_enabled) { goto end; } @@ -306,7 +305,7 @@ int timer_session_rotation_schedule_timer_stop(struct ltt_session *session) session->rotation_schedule_timer_enabled = false; /* The timer's reference to the session can be released safely. */ - session_put(session); + session_put(&session.get()); ret = 0; end: return ret; diff --git a/src/bin/lttng-sessiond/timer.hpp b/src/bin/lttng-sessiond/timer.hpp index c291ae6d2..7a5cc0232 100644 --- a/src/bin/lttng-sessiond/timer.hpp +++ b/src/bin/lttng-sessiond/timer.hpp @@ -22,16 +22,16 @@ struct timer_thread_parameters { int timer_signal_init(); /* Start a session's rotation pending check timer (one-shot mode). */ -int timer_session_rotation_pending_check_start(struct ltt_session *session, +int timer_session_rotation_pending_check_start(const ltt_session::locked_ref& session, unsigned int interval_us); /* Stop a session's rotation pending check timer. */ -int timer_session_rotation_pending_check_stop(ltt_session& session); +int timer_session_rotation_pending_check_stop(const ltt_session::locked_ref& session); /* Start a session's rotation schedule timer. */ -int timer_session_rotation_schedule_timer_start(struct ltt_session *session, +int timer_session_rotation_schedule_timer_start(const ltt_session::locked_ref& session, unsigned int interval_us); /* Stop a session's rotation schedule timer. */ -int timer_session_rotation_schedule_timer_stop(struct ltt_session *session); +int timer_session_rotation_schedule_timer_stop(const ltt_session::locked_ref& session); bool launch_timer_thread(struct timer_thread_parameters *timer_thread_parameters); diff --git a/src/bin/lttng-sessiond/ust-app.cpp b/src/bin/lttng-sessiond/ust-app.cpp index 2439d1e99..8f0375bc5 100644 --- a/src/bin/lttng-sessiond/ust-app.cpp +++ b/src/bin/lttng-sessiond/ust-app.cpp @@ -505,49 +505,49 @@ static void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan lttng::urcu::read_lock_guard read_lock; - ltt_session::ref session; try { - session = ltt_session::find_session(ua_chan->session->tracing_id); + const auto session = ltt_session::find_session(ua_chan->session->tracing_id); + + if (!session->ust_session) { + /* + * Not finding the session is not an error because there are + * multiple ways the channels can be torn down. + * + * 1) The session daemon can initiate the destruction of the + * ust app session after receiving a destroy command or + * during its shutdown/teardown. + * 2) The application, since we are in per-pid tracing, is + * unregistering and tearing down its ust app session. + * + * Both paths are protected by the session list lock which + * ensures that the accounting of lost packets and discarded + * events is done exactly once. The session is then unpublished + * from the session list, resulting in this condition. + */ + return; + } + + if (ua_chan->attr.overwrite) { + consumer_get_lost_packets(ua_chan->session->tracing_id, + ua_chan->key, + session->ust_session->consumer, + &lost); + } else { + consumer_get_discarded_events(ua_chan->session->tracing_id, + ua_chan->key, + session->ust_session->consumer, + &discarded); + } + uchan = trace_ust_find_channel_by_name(session->ust_session->domain_global.channels, + ua_chan->name); + if (!uchan) { + ERR("Missing UST channel to store discarded counters"); + return; + } } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { DBG_FMT("Failed to save per-pid lost/discarded counters: {}, location='{}'", ex.what(), ex.source_location); - } - - if (!session || !session->ust_session) { - /* - * Not finding the session is not an error because there are - * multiple ways the channels can be torn down. - * - * 1) The session daemon can initiate the destruction of the - * ust app session after receiving a destroy command or - * during its shutdown/teardown. - * 2) The application, since we are in per-pid tracing, is - * unregistering and tearing down its ust app session. - * - * Both paths are protected by the session list lock which - * ensures that the accounting of lost packets and discarded - * events is done exactly once. The session is then unpublished - * from the session list, resulting in this condition. - */ - return; - } - - if (ua_chan->attr.overwrite) { - consumer_get_lost_packets(ua_chan->session->tracing_id, - ua_chan->key, - session->ust_session->consumer, - &lost); - } else { - consumer_get_discarded_events(ua_chan->session->tracing_id, - ua_chan->key, - session->ust_session->consumer, - &discarded); - } - uchan = trace_ust_find_channel_by_name(session->ust_session->domain_global.channels, - ua_chan->name); - if (!uchan) { - ERR("Missing UST channel to store discarded counters"); return; } @@ -3446,7 +3446,6 @@ static int create_channel_per_uid(struct ust_app *app, int ret; struct buffer_reg_uid *reg_uid; struct buffer_reg_channel *buf_reg_chan; - ltt_session::ref session; enum lttng_error_code notification_ret; LTTNG_ASSERT(app); @@ -3457,6 +3456,10 @@ static int create_channel_per_uid(struct ust_app *app, DBG("UST app creating channel %s with per UID buffers", ua_chan->name); + /* Guaranteed to exist; will not throw. */ + const auto session = ltt_session::find_session(ua_sess->tracing_id); + ASSERT_SESSION_LIST_LOCKED(); + reg_uid = buffer_reg_uid_find(usess->id, app->abi.bits_per_long, app->uid); /* * The session creation handles the creation of this global registry @@ -3477,11 +3480,6 @@ static int create_channel_per_uid(struct ust_app *app, goto error; } - /* Guaranteed to exist; will not throw. */ - session = ltt_session::find_session(ua_sess->tracing_id); - ASSERT_LOCKED(session->_lock); - ASSERT_SESSION_LIST_LOCKED(); - /* * Create the buffers on the consumer side. This call populates the * ust app channel object with all streams and data object. @@ -3566,7 +3564,6 @@ static int create_channel_per_pid(struct ust_app *app, int ret; lsu::registry_session *registry; enum lttng_error_code cmd_ret; - ltt_session::ref session; uint64_t chan_reg_key; LTTNG_ASSERT(app); @@ -3582,6 +3579,11 @@ static int create_channel_per_pid(struct ust_app *app, /* The UST app session lock is held, registry shall not be null. */ LTTNG_ASSERT(registry); + /* Guaranteed to exist; will not throw. */ + const auto session = ltt_session::find_session(ua_sess->tracing_id); + ASSERT_LOCKED(session->_lock); + ASSERT_SESSION_LIST_LOCKED(); + /* Create and add a new channel registry to session. */ try { registry->add_channel(ua_chan->key); @@ -3593,11 +3595,6 @@ static int create_channel_per_pid(struct ust_app *app, goto error; } - /* Guaranteed to exist; will not throw. */ - session = ltt_session::find_session(ua_sess->tracing_id); - ASSERT_LOCKED(session->_lock); - ASSERT_SESSION_LIST_LOCKED(); - /* Create and get channel on the consumer side. */ ret = do_consumer_create_channel(usess, ua_sess, ua_chan, app->abi.bits_per_long, registry); if (ret < 0) { @@ -3890,7 +3887,6 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, int ret = 0; struct ust_app_channel *metadata; struct consumer_socket *socket; - ltt_session::ref session; LTTNG_ASSERT(ua_sess); LTTNG_ASSERT(app); @@ -3901,6 +3897,11 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, /* The UST app session is held registry shall not be null. */ LTTNG_ASSERT(locked_registry); + /* Guaranteed to exist; will not throw. */ + const auto session = ltt_session::find_session(ua_sess->tracing_id); + ASSERT_LOCKED(session->_lock); + ASSERT_SESSION_LIST_LOCKED(); + /* Metadata already exists for this registry or it was closed previously */ if (locked_registry->_metadata_key || locked_registry->_metadata_closed) { ret = 0; @@ -3939,11 +3940,6 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, */ locked_registry->_metadata_key = metadata->key; - /* Guaranteed to exist; will not throw. */ - session = ltt_session::find_session(ua_sess->tracing_id); - ASSERT_LOCKED(session->_lock); - ASSERT_SESSION_LIST_LOCKED(); - /* * Ask the metadata channel creation to the consumer. The metadata object * will be created by the consumer and kept their. However, the stream is @@ -7560,7 +7556,7 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess) * * Return LTTNG_OK on success or else an LTTng error code. */ -enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) +enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& session) { int ret; enum lttng_error_code cmd_ret = LTTNG_OK; @@ -7821,7 +7817,7 @@ error: * * Return LTTNG_OK on success or else an LTTng error code. */ -enum lttng_error_code ust_app_clear_session(struct ltt_session *session) +enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& session) { int ret; enum lttng_error_code cmd_ret = LTTNG_OK; @@ -7984,7 +7980,7 @@ end: * daemon as the same "offset" in a metadata stream will no longer point * to the same content. */ -enum lttng_error_code ust_app_open_packets(struct ltt_session *session) +enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& session) { enum lttng_error_code ret = LTTNG_OK; struct lttng_ht_iter iter; diff --git a/src/bin/lttng-sessiond/ust-app.hpp b/src/bin/lttng-sessiond/ust-app.hpp index 7a3f87591..f292753c0 100644 --- a/src/bin/lttng-sessiond/ust-app.hpp +++ b/src/bin/lttng-sessiond/ust-app.hpp @@ -426,11 +426,11 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess, uint64_t *discarded, uint64_t *lost); int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess); -enum lttng_error_code ust_app_rotate_session(struct ltt_session *session); +enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& session); enum lttng_error_code ust_app_create_channel_subdirectories(const struct ltt_ust_session *session); int ust_app_release_object(struct ust_app *app, struct lttng_ust_abi_object_data *data); -enum lttng_error_code ust_app_clear_session(struct ltt_session *session); -enum lttng_error_code ust_app_open_packets(struct ltt_session *session); +enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& session); +enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& session); int ust_app_setup_event_notifier_group(struct ust_app *app); @@ -705,7 +705,7 @@ static inline int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess return 0; } -static inline enum lttng_error_code ust_app_rotate_session(struct ltt_session *session +static inline enum lttng_error_code ust_app_rotate_session(const ltt_session::locked_ref& session __attribute__((unused))) { return LTTNG_ERR_UNK; @@ -724,13 +724,13 @@ static inline int ust_app_release_object(struct ust_app *app __attribute__((unus return 0; } -static inline enum lttng_error_code ust_app_clear_session(struct ltt_session *session +static inline enum lttng_error_code ust_app_clear_session(const ltt_session::locked_ref& session __attribute__((unused))) { return LTTNG_ERR_UNK; } -static inline enum lttng_error_code ust_app_open_packets(struct ltt_session *session +static inline enum lttng_error_code ust_app_open_packets(const ltt_session::locked_ref& session __attribute__((unused))) { return LTTNG_ERR_UNK; diff --git a/src/bin/lttng-sessiond/utils.cpp b/src/bin/lttng-sessiond/utils.cpp index b4d3c00a4..6960e6066 100644 --- a/src/bin/lttng-sessiond/utils.cpp +++ b/src/bin/lttng-sessiond/utils.cpp @@ -64,7 +64,7 @@ int loglevels_match(int a_loglevel_type, return match; } -const char *session_get_base_path(const struct ltt_session *session) +const char *session_get_base_path(const ltt_session::locked_ref& session) { return consumer_output_get_base_path(session->consumer); } diff --git a/src/bin/lttng-sessiond/utils.hpp b/src/bin/lttng-sessiond/utils.hpp index 83117f426..2f9bf8e62 100644 --- a/src/bin/lttng-sessiond/utils.hpp +++ b/src/bin/lttng-sessiond/utils.hpp @@ -8,8 +8,9 @@ #ifndef _LTT_UTILS_H #define _LTT_UTILS_H +#include "session.hpp" + struct lttng_ht; -struct ltt_session; struct consumer_output; const char *get_home_dir(); @@ -19,7 +20,7 @@ int loglevels_match(int a_loglevel_type, int b_loglevel_type, int b_loglevel_value, int loglevel_all_type); -const char *session_get_base_path(const struct ltt_session *session); +const char *session_get_base_path(const ltt_session::locked_ref& session); const char *consumer_output_get_base_path(const struct consumer_output *output); #endif /* _LTT_UTILS_H */ diff --git a/src/bin/lttng/exception.cpp b/src/bin/lttng/exception.cpp index 2a2db974a..799e9be22 100644 --- a/src/bin/lttng/exception.cpp +++ b/src/bin/lttng/exception.cpp @@ -12,9 +12,10 @@ #include -lttng::cli::no_default_session_error::no_default_session_error(const lttng::source_location &location) : +lttng::cli::no_default_session_error::no_default_session_error( + const lttng::source_location& location) : runtime_error(fmt::format("No default session found in `{}/.lttngrc`", - utils_get_home_dir() ?: "LTTNG_HOME"), + utils_get_home_dir() ?: "LTTNG_HOME"), location) { } diff --git a/src/bin/lttng/exception.hpp b/src/bin/lttng/exception.hpp index 3b24d2e88..f384e3d28 100644 --- a/src/bin/lttng/exception.hpp +++ b/src/bin/lttng/exception.hpp @@ -15,9 +15,8 @@ #include #include -#define LTTNG_THROW_CLI_NO_DEFAULT_SESSION() \ - throw lttng::cli::no_default_session_error( \ - LTTNG_SOURCE_LOCATION()) +#define LTTNG_THROW_CLI_NO_DEFAULT_SESSION() \ + throw lttng::cli::no_default_session_error(LTTNG_SOURCE_LOCATION()) namespace lttng { namespace cli { diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 8170e6e5a..257347ce2 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -99,6 +99,7 @@ libcommon_lgpl_la_SOURCES = \ log-level-rule.cpp \ make-unique.hpp \ make-unique-wrapper.hpp \ + meta-helpers.hpp \ mi-lttng.cpp mi-lttng.hpp \ notification.cpp \ payload.cpp payload.hpp \ @@ -106,6 +107,7 @@ libcommon_lgpl_la_SOURCES = \ pthread-lock.hpp \ random.cpp random.hpp \ readwrite.cpp readwrite.hpp \ + reference.hpp \ runas.cpp runas.hpp \ scope-exit.hpp \ session-descriptor.cpp \ diff --git a/src/common/exception.cpp b/src/common/exception.cpp index 50520c55c..4375f8159 100644 --- a/src/common/exception.cpp +++ b/src/common/exception.cpp @@ -21,8 +21,7 @@ lttng::ctl::error::error(const std::string& msg, lttng::posix_error::posix_error(const std::string& msg, unsigned int errno_code, const lttng::source_location& location) : - std::system_error(errno_code, std::generic_category()), - lttng::runtime_error(msg, location) + std::system_error(errno_code, std::generic_category()), lttng::runtime_error(msg, location) { } @@ -33,8 +32,8 @@ lttng::runtime_error::runtime_error(const std::string& msg, } lttng::allocation_failure::allocation_failure(const std::string& msg, -std::size_t allocation_size_, - const lttng::source_location& location) : + std::size_t allocation_size_, + const lttng::source_location& location) : lttng::runtime_error(msg, location), allocation_size(allocation_size_) { } diff --git a/src/common/make-unique-wrapper.hpp b/src/common/make-unique-wrapper.hpp index a0a4b541a..bfb5d6bb2 100644 --- a/src/common/make-unique-wrapper.hpp +++ b/src/common/make-unique-wrapper.hpp @@ -9,6 +9,7 @@ #define LTTNG_MAKE_UNIQUE_WRAPPER_H #include +#include #include @@ -39,21 +40,6 @@ namespace lttng { */ namespace memory { -template -struct create_deleter_class { - struct deleter { - void operator()(WrappedType *instance) const - { - DeleterFunction(instance); - } - }; - - std::unique_ptr operator()(WrappedType *instance) const - { - return std::unique_ptr(instance); - } -}; - /* * 'free' is a utility function for use with make_unique_wrapper. It makes it easier to * wrap raw pointers that have to be deleted with `free`. Using libc's 'free' as diff --git a/src/common/meta-helpers.hpp b/src/common/meta-helpers.hpp new file mode 100644 index 000000000..20000a104 --- /dev/null +++ b/src/common/meta-helpers.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_META_HELPERS_HPP +#define LTTNG_META_HELPERS_HPP + +#include + +/* + * Collection of meta-programming helpers. + * + * @see type-traits.hpp + */ +namespace lttng { +namespace memory { +template +struct create_deleter_class { + struct deleter { + void operator()(WrappedType *instance) const + { + DeleterFunction(instance); + } + }; + + std::unique_ptr operator()(WrappedType *instance) const + { + return std::unique_ptr(instance); + } +}; +} /* namespace memory */ +} /* namespace lttng */ + +#endif /* LTTNG_META_HELPERS_HPP */ diff --git a/src/common/reference.hpp b/src/common/reference.hpp new file mode 100644 index 000000000..ccf5f4e86 --- /dev/null +++ b/src/common/reference.hpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_REFERENCE_H +#define LTTNG_REFERENCE_H + +#include +#include + +namespace lttng { + +template +class non_copyable_reference { +public: + explicit non_copyable_reference(ReferencedType& instance) noexcept : _value(&instance) + { + } + + non_copyable_reference(non_copyable_reference&& other) noexcept : _value(other._value) + { + other._value = nullptr; + } + + non_copyable_reference() = delete; + non_copyable_reference(const non_copyable_reference&) = delete; + non_copyable_reference& operator=(non_copyable_reference&&) = delete; + non_copyable_reference& operator=(const non_copyable_reference&) = delete; + + ReferencedType& get() const noexcept + { + return *_value; + } + + ReferencedType *operator->() const noexcept + { + return _value; + } + + ReferencedType& operator*() const noexcept + { + return *_value; + } + + ~non_copyable_reference() + { + if (!_value) { + return; + } + + typename CustomDeleter::deleter del; + del(_value); + } + +private: + ReferencedType *_value = nullptr; +}; + +} /* namespace lttng */ + +#endif /* LTTNG_REFERENCE_H */ diff --git a/tests/unit/test_session.cpp b/tests/unit/test_session.cpp index af98c7b7e..f972c44bb 100644 --- a/tests/unit/test_session.cpp +++ b/tests/unit/test_session.cpp @@ -133,7 +133,7 @@ static int create_one_session(const char *name) /* * Test deletion of 1 session */ -static int destroy_one_session(struct ltt_session *session) +static int destroy_one_session(ltt_session::ref session) { int ret; char session_name[NAME_MAX]; @@ -141,8 +141,14 @@ static int destroy_one_session(struct ltt_session *session) strncpy(session_name, session->name, sizeof(session_name)); session_name[sizeof(session_name) - 1] = '\0'; - session_destroy(session); - session_put(session); + /* Reference of the session list. */ + ltt_session *weak_session_ptr = &session.get(); + { + /* Drop the reference that stems from the look-up. */ + const ltt_session::ref reference_to_drop = std::move(session); + } + + session_destroy(weak_session_ptr); ret = find_session_name(session_name); if (ret < 0) { @@ -207,25 +213,20 @@ static void test_validate_session() * sessions. */ const auto list_lock = lttng::sessiond::lock_session_list(); - ltt_session::ref session; try { - session = ltt_session::find_session(SESSION1); - } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { - } - - ok(session, "Validating session: session found"); + const auto session = ltt_session::find_session(SESSION1); + pass("Validating session: session found"); - if (session) { ok(session->kernel_session == nullptr && strlen(session->name), "Validating session: basic sanity check"); - } else { + + session->lock(); + session->unlock(); + } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { + fail("Validating session: session found"); skip(1, "Skipping session validation check as session was not found"); - return; } - - session->lock(); - session->unlock(); } static void test_destroy_session() @@ -238,20 +239,18 @@ static void test_destroy_session() * sessions. */ const auto list_lock = lttng::sessiond::lock_session_list(); - ltt_session::ref session; try { - session = ltt_session::find_session(SESSION1); - } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { - } + auto session = ltt_session::find_session(SESSION1); - ok(session, "Destroying session: session found"); + pass("Destroying session: session found"); - if (session) { - ok(destroy_one_session(session.release()) == 0, + ok(destroy_one_session(std::move(session)) == 0, "Destroying session: %s destroyed", SESSION1); - } else { + + } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) { + fail("Destroying session: session found"); skip(1, "Skipping session destruction as it was not found"); } } @@ -307,8 +306,11 @@ static void test_large_session_number() const auto list_lock = lttng::sessiond::lock_session_list(); for (i = 0; i < MAX_SESSIONS; i++) { cds_list_for_each_entry_safe (iter, tmp, &session_list->head, list) { - LTTNG_ASSERT(session_get(iter)); - ret = destroy_one_session(iter); + ret = destroy_one_session([iter]() { + session_get(iter); + return ltt_session::ref(*iter); + }()); + if (ret < 0) { diag("session %d destroy failed", i); ++failed; -- 2.34.1