#define _LGPL_SOURCE
#include "health-relayd.hpp"
#include "lttng-relayd.hpp"
+#include "utils.hpp"
#include <common/common.hpp>
#include <common/compat/getenv.hpp>
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()
{
#include <common/index/index.hpp>
#include <common/make-unique-wrapper.hpp>
#include <common/pthread-lock.hpp>
+#include <common/scope-exit.hpp>
#include <common/sessiond-comm/inet.hpp>
#include <common/sessiond-comm/relayd.hpp>
#include <common/sessiond-comm/sessiond-comm.hpp>
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<char, lttng::memory::free>(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<char, lttng::memory::free>(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<struct lttcomm_sock, lttcomm_destroy_sock>(
+ raw_sock);
+ }();
+ if (!sock) {
+ LTTNG_THROW_ALLOCATION_FAILURE_ERROR("Failed to allocate socket");
}
/*
*/
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();
}
/*
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;
}
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<char, lttng::memory::free>(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<char, lttng::memory::free>(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<char, lttng::memory::free>(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.
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(
}
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(
health_error();
ERR("Health error occurred in %s", __func__);
}
+
health_unregister(health_relayd);
rcu_unregister_thread();
DBG("Relay listener thread cleanup complete");
#include <common/common.hpp>
#include <common/defaults.hpp>
+#include <common/exception.hpp>
#include <common/path.hpp>
#include <common/utils.hpp>
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);
+ }
+}
*/
char *create_output_path(const char *path_name);
+void create_lttng_rundir_with_perm(const char* rundir);
#endif /* RELAYD_UTILS_H */
/* 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
/*