#include "load-session-thread.h"
#include "notification-thread.h"
#include "notification-thread-commands.h"
+#include "rotation-thread.h"
#include "syscall.h"
#include "agent.h"
#include "ht-cleanup.h"
+#include "sessiond-timer.h"
#define CONSUMERD_FILE "lttng-consumerd"
+static const char *help_msg =
+#ifdef LTTNG_EMBED_HELP
+#include <lttng-sessiond.8.h>
+#else
+NULL
+#endif
+;
+
const char *progname;
const char *tracing_group_name = DEFAULT_TRACING_GROUP;
static int tracing_group_name_override;
.err_sock = -1,
.cmd_sock = -1,
.channel_monitor_pipe = -1,
+ .channel_rotate_pipe = -1,
.pid_mutex = PTHREAD_MUTEX_INITIALIZER,
.lock = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
.err_sock = -1,
.cmd_sock = -1,
.channel_monitor_pipe = -1,
+ .channel_rotate_pipe = -1,
.pid_mutex = PTHREAD_MUTEX_INITIALIZER,
.lock = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
.err_sock = -1,
.cmd_sock = -1,
.channel_monitor_pipe = -1,
+ .channel_rotate_pipe = -1,
.pid_mutex = PTHREAD_MUTEX_INITIALIZER,
.lock = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
int apps_cmd_notify_pipe[2] = { -1, -1 };
+/*
+ * Pipe to wakeup the rotation thread when the
+ * LTTNG_SESSIOND_SIG_ROTATE_PENDING signal is caught.
+ */
+static int rotate_timer_pipe[2] = { -1, -1 };
+
/* Pthread, Mutexes and Semaphores */
static pthread_t apps_thread;
static pthread_t apps_notify_thread;
static pthread_t agent_reg_thread;
static pthread_t load_session_thread;
static pthread_t notification_thread;
+static pthread_t rotation_thread;
+static pthread_t timer_thread;
/*
* UST registration command queue. This queue is tied with a futex and uses a N
/* Notification thread handle. */
struct notification_thread_handle *notification_thread_handle;
+/* Rotation thread handle. */
+struct rotation_thread_handle *rotation_thread_handle;
+
/* Global hash tables */
struct lttng_ht *agent_apps_ht_by_sock = NULL;
* NR_LTTNG_SESSIOND_READY must match the number of calls to
* sessiond_notify_ready().
*/
-#define NR_LTTNG_SESSIOND_READY 4
+#define NR_LTTNG_SESSIOND_READY 5
int lttng_sessiond_ready = NR_LTTNG_SESSIOND_READY;
int sessiond_check_thread_quit_pipe(int fd, uint32_t events)
PERROR("UST consumerd64 channel monitor pipe close");
}
}
+ if (kconsumer_data.channel_rotate_pipe >= 0) {
+ ret = close(kconsumer_data.channel_rotate_pipe);
+ if (ret < 0) {
+ PERROR("kernel consumer channel rotate pipe close");
+ }
+ }
+ if (ustconsumer32_data.channel_rotate_pipe >= 0) {
+ ret = close(ustconsumer32_data.channel_rotate_pipe);
+ if (ret < 0) {
+ PERROR("UST consumerd32 channel rotate pipe close");
+ }
+ }
+ if (ustconsumer64_data.channel_rotate_pipe >= 0) {
+ ret = close(ustconsumer64_data.channel_rotate_pipe);
+ if (ret < 0) {
+ PERROR("UST consumerd64 channel rotate pipe close");
+ }
+ }
}
/*
ret = waitpid(consumer_data->pid, &status, 0);
if (ret == -1) {
PERROR("consumerd waitpid pid: %d", consumer_data->pid)
- }
- if (!WIFEXITED(status)) {
+ } else if (!WIFEXITED(status)) {
ERR("consumerd termination with error: %d",
WEXITSTATUS(ret));
}
health_code_update();
/*
- * Transfer the write-end of the channel monitoring pipe to the
- * by issuing a SET_CHANNEL_MONITOR_PIPE command.
+ * Transfer the write-end of the channel monitoring and rotate pipe
+ * to the consumer by issuing a SET_CHANNEL_MONITOR_PIPE and
+ * SET_CHANNEL_ROTATE_PIPE commands.
*/
cmd_socket_wrapper = consumer_allocate_socket(&consumer_data->cmd_sock);
if (!cmd_socket_wrapper) {
if (ret) {
goto error;
}
+
+ ret = consumer_send_channel_rotate_pipe(cmd_socket_wrapper,
+ consumer_data->channel_rotate_pipe);
+ if (ret) {
+ goto error;
+ }
+
/* Discard the socket wrapper as it is no longer needed. */
consumer_destroy_socket(cmd_socket_wrapper);
cmd_socket_wrapper = NULL;
DBG("[thread] Dispatch UST command started");
- while (!CMM_LOAD_SHARED(dispatch_thread_exit)) {
+ for (;;) {
health_code_update();
/* Atomically prepare the queue futex */
futex_nto1_prepare(&ust_cmd_queue.futex);
+ if (CMM_LOAD_SHARED(dispatch_thread_exit)) {
+ break;
+ }
+
do {
struct ust_app *app = NULL;
ust_cmd = NULL;
} else {
DBG("Could not find any valid consumerd executable");
ret = -EINVAL;
- break;
+ goto error;
}
DBG("Using kernel consumer at: %s", consumer_to_use);
- ret = execl(consumer_to_use,
+ (void) execl(consumer_to_use,
"lttng-consumerd", verbosity, "-k",
"--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
"--consumerd-err-sock", consumer_data->err_unix_sock_path,
}
}
DBG("Using 64-bit UST consumer at: %s", consumerd64_bin);
- ret = execl(consumerd64_bin, "lttng-consumerd", verbosity, "-u",
+ (void) execl(consumerd64_bin, "lttng-consumerd", verbosity, "-u",
"--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
"--consumerd-err-sock", consumer_data->err_unix_sock_path,
"--group", tracing_group_name,
}
}
DBG("Using 32-bit UST consumer at: %s", consumerd32_bin);
- ret = execl(consumerd32_bin, "lttng-consumerd", verbosity, "-u",
+ (void) execl(consumerd32_bin, "lttng-consumerd", verbosity, "-u",
"--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
"--consumerd-err-sock", consumer_data->err_unix_sock_path,
"--group", tracing_group_name,
kernel_tracer_fd = open(module_proc_lttng, O_RDWR);
if (kernel_tracer_fd < 0) {
DBG("Failed to open %s", module_proc_lttng);
- ret = -1;
goto error_open;
}
goto error_modules;
}
+ ret = kernel_supports_ring_buffer_snapshot_sample_positions(
+ kernel_tracer_fd);
+ if (ret < 0) {
+ goto error_modules;
+ }
+
+ if (ret < 1) {
+ WARN("Kernel tracer does not support buffer monitoring. "
+ "The monitoring timer of channels in the kernel domain "
+ "will be set to 0 (disabled).");
+ }
+
DBG("Kernel tracer fd %d", kernel_tracer_fd);
return 0;
/* Create directory(ies) on local filesystem. */
if (session->kernel_session->consumer->type == CONSUMER_DST_LOCAL &&
- strlen(session->kernel_session->consumer->dst.trace_path) > 0) {
+ strlen(session->kernel_session->consumer->dst.session_root_path) > 0) {
ret = run_as_mkdir_recursive(
- session->kernel_session->consumer->dst.trace_path,
+ session->kernel_session->consumer->dst.session_root_path,
S_IRWXU | S_IRWXG, session->uid, session->gid);
if (ret < 0) {
if (errno != EEXIST) {
case LTTNG_REGENERATE_STATEDUMP:
case LTTNG_REGISTER_TRIGGER:
case LTTNG_UNREGISTER_TRIGGER:
+ case LTTNG_ROTATE_SESSION:
+ case LTTNG_ROTATE_PENDING:
need_domain = 0;
break;
default:
case LTTNG_LIST_SYSCALLS:
case LTTNG_LIST_TRACKER_PIDS:
case LTTNG_DATA_PENDING:
+ case LTTNG_ROTATE_SESSION:
+ case LTTNG_ROTATE_PENDING:
break;
default:
/* Setup lttng message with no payload */
notification_thread_handle);
break;
}
+ case LTTNG_ROTATE_SESSION:
+ {
+ struct lttng_rotate_session_return *rotate_return = NULL;
+
+ ret = cmd_rotate_session(cmd_ctx->session, &rotate_return);
+ if (ret < 0) {
+ ret = -ret;
+ fprintf(stderr, "cmd ret: %d\n", ret);
+ goto error;
+ }
+
+ ret = setup_lttng_msg_no_cmd_header(cmd_ctx, rotate_return,
+ sizeof(struct lttng_rotate_session_return));
+ free(rotate_return);
+ if (ret < 0) {
+ ret = -ret;
+ goto error;
+ }
+
+ ret = LTTNG_OK;
+ break;
+ }
+ case LTTNG_ROTATE_PENDING:
+ {
+ struct lttng_rotate_pending_return *pending_return = NULL;
+
+ ret = cmd_rotate_pending(cmd_ctx->session, &pending_return,
+ cmd_ctx->lsm->u.rotate_pending.rotate_id);
+ if (ret < 0) {
+ ret = -ret;
+ goto error;
+ }
+
+ ret = setup_lttng_msg_no_cmd_header(cmd_ctx, pending_return,
+ sizeof(struct lttng_rotate_session_handle));
+ free(pending_return);
+ if (ret < 0) {
+ ret = -ret;
+ goto error;
+ }
+
+ ret = LTTNG_OK;
+ break;
+ }
default:
ret = LTTNG_ERR_UND;
break;
}
/* Set return code */
cmd_ctx->llm->ret_code = ret;
+ fprintf(stderr, "llm ret: %d\n", ret);
setup_error:
if (cmd_ctx->session) {
session_unlock(cmd_ctx->session);
tracing_group_name_override = 1;
}
} else if (string_match(optname, "help") || opt == 'h') {
- ret = utils_show_man_page(8, "lttng-sessiond");
+ ret = utils_show_help(8, "lttng-sessiond", help_msg);
if (ret) {
- ERR("Cannot view man page lttng-sessiond(8)");
+ ERR("Cannot show --help for `lttng-sessiond`");
perror("exec");
}
exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
DBG2("Creating consumer directory: %s", path);
ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP);
- if (ret < 0) {
- if (errno != EEXIST) {
- PERROR("mkdir");
- ERR("Failed to create %s", path);
- goto error;
- }
- ret = -1;
+ if (ret < 0 && errno != EEXIST) {
+ PERROR("mkdir");
+ ERR("Failed to create %s", path);
+ goto error;
}
if (is_root) {
ret = chown(path, 0, utils_get_group_id(tracing_group_name));
struct lttng_pipe *ust32_channel_monitor_pipe = NULL,
*ust64_channel_monitor_pipe = NULL,
*kernel_channel_monitor_pipe = NULL;
+ bool notification_thread_running = false;
+ bool timer_thread_running = false;
+ struct lttng_pipe *ust32_channel_rotate_pipe = NULL,
+ *ust64_channel_rotate_pipe = NULL,
+ *kernel_channel_rotate_pipe = NULL;
init_kernel_workarounds();
goto exit_set_signal_handler;
}
+ if (sessiond_timer_signal_init()) {
+ retval = -1;
+ goto exit_set_signal_handler;
+ }
+
setup_consumerd_path();
page_size = sysconf(_SC_PAGESIZE);
retval = -1;
goto exit_init_data;
}
+ kernel_channel_rotate_pipe = lttng_pipe_open(0);
+ if (!kernel_channel_rotate_pipe) {
+ ERR("Failed to create kernel consumer channel rotate pipe");
+ retval = -1;
+ goto exit_init_data;
+ }
+ kconsumer_data.channel_rotate_pipe =
+ lttng_pipe_release_writefd(
+ kernel_channel_rotate_pipe);
+ if (kconsumer_data.channel_rotate_pipe < 0) {
+ retval = -1;
+ goto exit_init_data;
+ }
} else {
home_path = utils_get_home_dir();
if (home_path == NULL) {
retval = -1;
goto exit_init_data;
}
+ ust32_channel_rotate_pipe = lttng_pipe_open(0);
+ if (!ust32_channel_rotate_pipe) {
+ ERR("Failed to create 32-bit user space consumer channel rotate pipe");
+ retval = -1;
+ goto exit_init_data;
+ }
+ ustconsumer32_data.channel_rotate_pipe = lttng_pipe_release_writefd(
+ ust32_channel_rotate_pipe);
+ if (ustconsumer32_data.channel_rotate_pipe < 0) {
+ retval = -1;
+ goto exit_init_data;
+ }
+
+ /*
+ * Create the rotate_timer_pipe as non blocking because we have to
+ * write in it from the sighandler.
+ */
+ ret = utils_create_pipe_cloexec_nonblock(rotate_timer_pipe);
+ if (ret < 0) {
+ ERR("Failed to create rotate pending pipe");
+ retval = -1;
+ goto exit_init_data;
+ }
/* 64 bits consumerd path setup */
ret = snprintf(ustconsumer64_data.err_unix_sock_path, PATH_MAX,
retval = -1;
goto exit_init_data;
}
+ ust64_channel_rotate_pipe = lttng_pipe_open(0);
+ if (!ust64_channel_rotate_pipe) {
+ ERR("Failed to create 64-bit user space consumer channel rotate pipe");
+ retval = -1;
+ goto exit_init_data;
+ }
+ ustconsumer64_data.channel_rotate_pipe = lttng_pipe_release_writefd(
+ ust64_channel_rotate_pipe);
+ if (ustconsumer64_data.channel_rotate_pipe < 0) {
+ retval = -1;
+ goto exit_init_data;
+ }
/*
* See if daemon already exist.
stop_threads();
goto exit_notification;
}
+ notification_thread_running = true;
+
+ /* rotation_thread_data acquires the pipes' read side. */
+ rotation_thread_handle = rotation_thread_handle_create(
+ ust32_channel_rotate_pipe,
+ ust64_channel_rotate_pipe,
+ kernel_channel_rotate_pipe,
+ thread_quit_pipe[0],
+ rotate_timer_pipe[0]);
+ if (!rotation_thread_handle) {
+ retval = -1;
+ ERR("Failed to create rotation thread shared data");
+ stop_threads();
+ goto exit_rotation;
+ }
+
+ /* Create timer thread. */
+ ret = pthread_create(&timer_thread, default_pthread_attr(),
+ sessiond_timer_thread, NULL);
+ if (ret) {
+ errno = ret;
+ PERROR("pthread_create timer");
+ retval = -1;
+ stop_threads();
+ goto exit_notification;
+ }
+ timer_thread_running = true;
+
+ /* Create rotation thread. */
+ ret = pthread_create(&rotation_thread, default_pthread_attr(),
+ thread_rotation, rotation_thread_handle);
+ if (ret) {
+ errno = ret;
+ PERROR("pthread_create rotation");
+ retval = -1;
+ stop_threads();
+ goto exit_rotation;
+ }
/* Create thread to manage the client socket */
ret = pthread_create(&client_thread, default_pthread_attr(),
}
exit_client:
+exit_rotation:
exit_notification:
ret = pthread_join(health_thread, &status);
if (ret) {
* of the active session and channels at the moment of the teardown.
*/
if (notification_thread_handle) {
- notification_thread_command_quit(notification_thread_handle);
+ if (notification_thread_running) {
+ notification_thread_command_quit(
+ notification_thread_handle);
+ ret = pthread_join(notification_thread, &status);
+ if (ret) {
+ errno = ret;
+ PERROR("pthread_join notification thread");
+ retval = -1;
+ }
+ }
notification_thread_handle_destroy(notification_thread_handle);
}
- ret = pthread_join(notification_thread, &status);
+ if (rotation_thread_handle) {
+ rotation_thread_handle_destroy(rotation_thread_handle);
+ ret = close(rotate_timer_pipe[0]);
+ if (ret < 0) {
+ PERROR("Close rotate pending pipe");
+ retval = -1;
+ }
+ ret = close(rotate_timer_pipe[1]);
+ if (ret < 0) {
+ PERROR("Close rotate pending pipe");
+ retval = -1;
+ }
+ }
+
+ ret = pthread_join(rotation_thread, &status);
if (ret) {
errno = ret;
- PERROR("pthread_join notification thread");
+ PERROR("pthread_join rotation thread");
retval = -1;
}
+ if (timer_thread_running) {
+ kill(getpid(), LTTNG_SESSIOND_SIG_EXIT);
+ ret = pthread_join(timer_thread, &status);
+ if (ret) {
+ errno = ret;
+ PERROR("pthread_join timer thread");
+ retval = -1;
+ }
+ }
+
rcu_thread_offline();
rcu_unregister_thread();
lttng_pipe_destroy(ust32_channel_monitor_pipe);
lttng_pipe_destroy(ust64_channel_monitor_pipe);
lttng_pipe_destroy(kernel_channel_monitor_pipe);
+ lttng_pipe_destroy(ust32_channel_rotate_pipe);
+ lttng_pipe_destroy(ust64_channel_rotate_pipe);
+ lttng_pipe_destroy(kernel_channel_rotate_pipe);
exit_ht_cleanup:
health_app_destroy(health_sessiond);