From 2ae89306d8470298d56a5f51ee855bd3e1fad96c Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Fri, 25 Oct 2024 20:58:46 +0000 Subject: [PATCH] lttng-relayd: Write control, data, and live ports to rundir MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: I7ff61e5dc6612de80641ac36fa98abdce3da97b4 Signed-off-by: Kienan Stewart Signed-off-by: Jérémie Galarneau --- src/bin/lttng-relayd/health-relayd.cpp | 47 +--------- src/bin/lttng-relayd/live.cpp | 124 +++++++++++++++++-------- src/bin/lttng-relayd/main.cpp | 62 ++++++++++++- src/bin/lttng-relayd/utils.cpp | 48 ++++++++++ src/bin/lttng-relayd/utils.hpp | 1 + src/common/defaults.hpp | 3 + 6 files changed, 198 insertions(+), 87 deletions(-) diff --git a/src/bin/lttng-relayd/health-relayd.cpp b/src/bin/lttng-relayd/health-relayd.cpp index 17376757b..9f131029e 100644 --- a/src/bin/lttng-relayd/health-relayd.cpp +++ b/src/bin/lttng-relayd/health-relayd.cpp @@ -8,6 +8,7 @@ #define _LGPL_SOURCE #include "health-relayd.hpp" #include "lttng-relayd.hpp" +#include "utils.hpp" #include #include @@ -64,52 +65,6 @@ int send_unix_sock(int sock, void *buf, size_t len) return lttcomm_send_unix_sock(sock, buf, len); } -void create_lttng_rundir_with_perm(const char *rundir) -{ - DBG_FMT("Creating LTTng run directory: `%s`", rundir); - - const auto mkdir_ret = mkdir(rundir, S_IRWXU); - if (mkdir_ret < 0) { - if (errno != EEXIST) { - LTTNG_THROW_POSIX(fmt::format("Failed to create rundir: path=`{}`", rundir), - errno); - } - } - - const auto is_root = !getuid(); - if (!is_root) { - /* Nothing more to do. */ - return; - } - - gid_t gid; - const auto get_group_id_ret = utils_get_group_id(tracing_group_name, true, &gid); - if (get_group_id_ret) { - /* Default to root group. */ - gid = 0; - } - - const auto chown_ret = chown(rundir, 0, gid); - if (chown_ret < 0) { - LTTNG_THROW_POSIX( - fmt::format("Failed to set group on rundir: path=`{}`, group_id={}", - rundir, - gid), - errno); - } - - const auto permission_mask = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | - S_IXOTH; - const auto chmod_ret = chmod(rundir, permission_mask); - if (chmod_ret < 0) { - LTTNG_THROW_POSIX( - fmt::format( - "Failed to set permissions on rundir: path=`{}`, permission={:o}", - rundir, - permission_mask), - errno); - } -} void parse_health_env() { diff --git a/src/bin/lttng-relayd/live.cpp b/src/bin/lttng-relayd/live.cpp index 48d014956..4c703421c 100644 --- a/src/bin/lttng-relayd/live.cpp +++ b/src/bin/lttng-relayd/live.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -754,14 +755,44 @@ end: static struct lttcomm_sock *init_socket(struct lttng_uri *uri, const char *name) { int ret, sock_fd; - struct lttcomm_sock *sock = nullptr; char uri_str[LTTNG_PATH_MAX]; - char *formatted_name = nullptr; + char relayd_live_port_path[PATH_MAX]; - sock = lttcomm_alloc_sock_from_uri(uri); - if (sock == nullptr) { - ERR("Allocating socket"); - goto error; + const auto rundir_path = + lttng::make_unique_wrapper(utils_get_rundir(0)); + if (!rundir_path) { + LTTNG_THROW_ALLOCATION_FAILURE_ERROR( + "Failed to determine RUNDIR for socket creation"); + } + + auto relayd_rundir_path = [&rundir_path]() { + char *raw_relayd_path = nullptr; + const auto fmt_ret = + asprintf(&raw_relayd_path, DEFAULT_RELAYD_PATH, rundir_path.get()); + if (fmt_ret < 0) { + LTTNG_THROW_POSIX("Failed to format relayd rundir path", errno); + } + + return lttng::make_unique_wrapper(raw_relayd_path); + }(); + + create_lttng_rundir_with_perm(rundir_path.get()); + create_lttng_rundir_with_perm(relayd_rundir_path.get()); + ret = snprintf(relayd_live_port_path, + sizeof(relayd_live_port_path), + DEFAULT_RELAYD_LIVE_PORT_PATH, + relayd_rundir_path.get()); + if (ret < 0) { + LTTNG_THROW_ERROR("Failed to format relayd live port path"); + } + + auto sock = [uri]() { + auto raw_sock = lttcomm_alloc_sock_from_uri(uri); + return lttng::make_unique_wrapper( + raw_sock); + }(); + if (!sock) { + LTTNG_THROW_ALLOCATION_FAILURE_ERROR("Failed to allocate socket"); } /* @@ -770,47 +801,65 @@ static struct lttcomm_sock *init_socket(struct lttng_uri *uri, const char *name) */ ret = uri_to_str_url(uri, uri_str, sizeof(uri_str)); uri_str[sizeof(uri_str) - 1] = '\0'; - if (ret >= 0) { - ret = asprintf(&formatted_name, "%s socket @ %s", name, uri_str); - if (ret < 0) { - formatted_name = nullptr; - } - } - + auto formatted_name = + fmt::format("'{}' socket @ '{}'", name, ret < 0 ? uri_str : "Unknown"); + /* Using '&' requires an lvalue. Using `formatted_name.data()` returns an rvalue. */ + auto formatted_name_data = formatted_name.data(); ret = fd_tracker_open_unsuspendable_fd(the_fd_tracker, &sock_fd, - (const char **) (formatted_name ? &formatted_name : - nullptr), + (const char **) &formatted_name_data, 1, create_sock, - sock); + sock.get()); if (ret) { - PERROR("Failed to create \"%s\" socket", formatted_name ?: "Unknown"); - goto error; - } - DBG("Listening on %s socket %d", name, sock->fd); + LTTNG_THROW_ERROR(lttng::format("Failed to create \"{}\" socket", formatted_name)); + } + + auto fd_tracker_remove_on_error = + lttng::make_scope_exit([&sock, &sock_fd, &relayd_live_port_path]() noexcept { + if (sock.get() != nullptr) { + if (sock->fd >= 0) { + fd_tracker_close_unsuspendable_fd(the_fd_tracker, + &sock_fd, + 1, + close_sock, + sock.get()); + } + } + }); - ret = sock->ops->bind(sock); + DBG("Listening on %s socket %d", name, sock->fd); + ret = sock->ops->bind(sock.get()); if (ret < 0) { - PERROR("Failed to bind lttng-live socket"); - goto error; + LTTNG_THROW_POSIX("Failed to bind lttng-live socket", errno); } - DBG("Bound %s socket fd %d to port %d", name, sock->fd, ntohs(sock->sockaddr.addr.sin.sin_port)); - ret = sock->ops->listen(sock, -1); - if (ret < 0) { - goto error; + if (utils_create_pid_file((pid_t) ntohs(sock->sockaddr.addr.sin.sin_port), + relayd_live_port_path)) { + LTTNG_THROW_ERROR("Failed to create and write live port path"); } - free(formatted_name); - return sock; + auto unlink_relayd_live_port_path_on_error = + lttng::make_scope_exit([&relayd_live_port_path]() noexcept { + if (unlink(relayd_live_port_path)) { + WARN_FMT("Failed to remove live port file at path '{}'", + relayd_live_port_path); + } + }); -error: - if (sock) { - lttcomm_destroy_sock(sock); + DBG("Bound %s socket fd %d to port %d", + name, + sock->fd, + ntohs(sock->sockaddr.addr.sin.sin_port)); + ret = sock->ops->listen(sock.get(), -1); + if (ret < 0) { + LTTNG_THROW_ERROR("Failed to listen on lttng-live socket"); } - free(formatted_name); - return nullptr; + + /* Stop destructors from being invoked when the scope_exits go out of scope. */ + fd_tracker_remove_on_error.disarm(); + unlink_relayd_live_port_path_on_error.disarm(); + return sock.release(); } /* @@ -829,9 +878,10 @@ static void *thread_listener(void *data __attribute__((unused))) health_register(health_relayd, HEALTH_RELAYD_TYPE_LIVE_LISTENER); health_code_update(); - - live_control_sock = init_socket(live_uri, "Live listener"); - if (!live_control_sock) { + try { + live_control_sock = init_socket(live_uri, "Live listener"); + } catch(const lttng::runtime_error& ex) { + ERR("Failed to initialize live socket: %s", ex.what()); goto error_sock_control; } diff --git a/src/bin/lttng-relayd/main.cpp b/src/bin/lttng-relayd/main.cpp index 0045c5b5f..f8fcee2a1 100644 --- a/src/bin/lttng-relayd/main.cpp +++ b/src/bin/lttng-relayd/main.cpp @@ -1088,25 +1088,74 @@ static void *relay_thread_listener(void *data __attribute__((unused))) int i, ret, err = -1; uint32_t nb_fd; struct lttng_poll_event events; - struct lttcomm_sock *control_sock, *data_sock; + char relayd_data_port_path[PATH_MAX]; + char relayd_control_port_path[PATH_MAX]; + struct lttcomm_sock *control_sock = nullptr, *data_sock = nullptr; + auto relayd_rundir_path = lttng::make_unique_wrapper(nullptr); DBG("[thread] Relay listener started"); rcu_register_thread(); health_register(health_relayd, HEALTH_RELAYD_TYPE_LISTENER); - health_code_update(); + const auto rundir_path = + lttng::make_unique_wrapper(utils_get_rundir(0)); + if (!rundir_path) { + ERR("Failed to determine RUNDIR for listener thread port files"); + goto error_sock_control; + } + + relayd_rundir_path = [&rundir_path]() { + char *raw_relayd_path = nullptr; + const auto fmt_ret = + asprintf(&raw_relayd_path, DEFAULT_RELAYD_PATH, rundir_path.get()); + if (fmt_ret < 0) { + LTTNG_THROW_POSIX("Failed to fomat relayd rundir path", errno); + } + + return lttng::make_unique_wrapper(raw_relayd_path); + }(); + + create_lttng_rundir_with_perm(rundir_path.get()); + create_lttng_rundir_with_perm(relayd_rundir_path.get()); + ret = snprintf(relayd_control_port_path, sizeof(relayd_control_port_path), DEFAULT_RELAYD_CONTROL_PORT_PATH, relayd_rundir_path.get()); + if (ret < 0) { + ERR("Failed to format relayd_control_port_path"); + goto error_sock_control; + } + + ret = snprintf(relayd_data_port_path, sizeof(relayd_data_port_path), DEFAULT_RELAYD_DATA_PORT_PATH, relayd_rundir_path.get()); + if (ret < 0) { + ERR("Failed to format relayd_data_port_path"); + goto error_sock_control; + } + + ret = 0; + health_code_update(); control_sock = relay_socket_create(control_uri, "Control listener"); if (!control_sock) { goto error_sock_control; } + if (auto _ret = utils_create_value_file(ntohs(control_sock->sockaddr.addr.sin.sin_port), + relayd_control_port_path)) { + ERR_FMT("Failed to create control port path file: port={}, path=`{}`, ret={}", ntohs(control_sock->sockaddr.addr.sin.sin_port), relayd_control_port_path, _ret); + goto error_create_poll; + goto error_sock_relay; + } + data_sock = relay_socket_create(data_uri, "Data listener"); if (!data_sock) { goto error_sock_relay; } + if (auto _ret = utils_create_value_file(ntohs(data_sock->sockaddr.addr.sin.sin_port), + relayd_data_port_path)) { + ERR_FMT("Failed to create data port path file: port={}, path=`{}`, ret={}", ntohs(data_sock->sockaddr.addr.sin.sin_port), relayd_data_port_path, _ret); + goto error_create_poll; + } + /* * Pass 3 as size here for the thread quit pipe, control and * data socket. @@ -1246,7 +1295,9 @@ error_poll_add: error_testpoint: (void) fd_tracker_util_poll_clean(the_fd_tracker, &events); error_create_poll: - if (data_sock->fd >= 0) { + DBG("Removing '%s'", relayd_data_port_path); + (void) unlink(relayd_data_port_path); + if (data_sock != nullptr && data_sock->fd >= 0) { int data_sock_fd = data_sock->fd; ret = fd_tracker_close_unsuspendable_fd( @@ -1258,7 +1309,9 @@ error_create_poll: } lttcomm_destroy_sock(data_sock); error_sock_relay: - if (control_sock->fd >= 0) { + DBG("Removing '%s'", relayd_control_port_path); + (void) unlink(relayd_control_port_path); + if (control_sock != nullptr && control_sock->fd >= 0) { int control_sock_fd = control_sock->fd; ret = fd_tracker_close_unsuspendable_fd( @@ -1274,6 +1327,7 @@ error_sock_control: health_error(); ERR("Health error occurred in %s", __func__); } + health_unregister(health_relayd); rcu_unregister_thread(); DBG("Relay listener thread cleanup complete"); diff --git a/src/bin/lttng-relayd/utils.cpp b/src/bin/lttng-relayd/utils.cpp index 3d02f6044..fc968ecd1 100644 --- a/src/bin/lttng-relayd/utils.cpp +++ b/src/bin/lttng-relayd/utils.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -76,3 +77,50 @@ char *create_output_path(const char *path_name) return create_output_path_noauto(path_name); } } + +void create_lttng_rundir_with_perm(const char *rundir) +{ + DBG_FMT("Creating LTTng run directory: `{}`", rundir); + + const auto mkdir_ret = mkdir(rundir, S_IRWXU); + if (mkdir_ret < 0) { + if (errno != EEXIST) { + LTTNG_THROW_POSIX(fmt::format("Failed to create rundir: path=`{}`", rundir), + errno); + } + } + + const auto is_root = !getuid(); + if (!is_root) { + /* Nothing more to do. */ + return; + } + + gid_t gid; + const auto get_group_id_ret = utils_get_group_id(tracing_group_name, true, &gid); + if (get_group_id_ret) { + /* Default to root group. */ + gid = 0; + } + + const auto chown_ret = chown(rundir, 0, gid); + if (chown_ret < 0) { + LTTNG_THROW_POSIX( + fmt::format("Failed to set group on rundir: path=`{}`, group_id={}", + rundir, + gid), + errno); + } + + const auto permission_mask = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | + S_IXOTH; + const auto chmod_ret = chmod(rundir, permission_mask); + if (chmod_ret < 0) { + LTTNG_THROW_POSIX( + fmt::format( + "Failed to set permissions on rundir: path=`{}`, permission={:o}", + rundir, + permission_mask), + errno); + } +} diff --git a/src/bin/lttng-relayd/utils.hpp b/src/bin/lttng-relayd/utils.hpp index b02a791b1..c42ee82ae 100644 --- a/src/bin/lttng-relayd/utils.hpp +++ b/src/bin/lttng-relayd/utils.hpp @@ -11,5 +11,6 @@ */ char *create_output_path(const char *path_name); +void create_lttng_rundir_with_perm(const char* rundir); #endif /* RELAYD_UTILS_H */ diff --git a/src/common/defaults.hpp b/src/common/defaults.hpp index a0c218622..5c296a389 100644 --- a/src/common/defaults.hpp +++ b/src/common/defaults.hpp @@ -85,6 +85,9 @@ /* Relayd path */ #define DEFAULT_RELAYD_RUNDIR "%s" #define DEFAULT_RELAYD_PATH DEFAULT_RELAYD_RUNDIR "/relayd" +#define DEFAULT_RELAYD_CONTROL_PORT_PATH DEFAULT_LTTNG_EXPLICIT_RUNDIR "/control.port" +#define DEFAULT_RELAYD_DATA_PORT_PATH DEFAULT_LTTNG_EXPLICIT_RUNDIR "/data.port" +#define DEFAULT_RELAYD_LIVE_PORT_PATH DEFAULT_LTTNG_EXPLICIT_RUNDIR "/live.port" #define DEFAULT_RELAYD_MIN_FD_POOL_SIZE 100 /* -- 2.39.5