/*
- * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
- * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * 2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2 only,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: GPL-2.0-only
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define _LGPL_SOURCE
#include "event.h"
#include "kernel.h"
#include "kernel-consumer.h"
-#include "modprobe.h"
#include "shm.h"
-#include "ust-ctl.h"
+#include "lttng-ust-ctl.h"
#include "ust-consumer.h"
#include "utils.h"
#include "fd-limit.h"
#include "notification-thread.h"
#include "notification-thread-commands.h"
#include "rotation-thread.h"
-#include "lttng-syscall.h"
#include "agent.h"
#include "ht-cleanup.h"
#include "sessiond-config.h"
const char *progname;
static int lockfile_fd = -1;
+static int opt_print_version;
/* Set to 1 when a SIGUSR1 signal is received. */
static int recv_child_signal;
*/
static struct ust_cmd_queue ust_cmd_queue;
-static const char *module_proc_lttng = "/proc/lttng";
-
/*
* Section name to look for in the daemon configuration file.
*/
pthread_mutex_destroy(&session_list->lock);
- wait_consumer(&kconsumer_data);
- wait_consumer(&ustconsumer64_data);
- wait_consumer(&ustconsumer32_data);
-
DBG("Cleaning up all agent apps");
agent_app_ht_clean();
-
DBG("Closing all UST sockets");
ust_app_clean_list();
buffer_reg_destroy_registries();
+ close_consumer_sockets();
+
+ wait_consumer(&kconsumer_data);
+ wait_consumer(&ustconsumer64_data);
+ wait_consumer(&ustconsumer32_data);
+
if (is_root && !config.no_kernel) {
- DBG2("Closing kernel fd");
- if (kernel_tracer_fd >= 0) {
- ret = close(kernel_tracer_fd);
- if (ret) {
- PERROR("close");
- }
- }
- DBG("Unloading kernel modules");
- modprobe_remove_lttng_all();
- free(syscall_table);
+ cleanup_kernel_tracer();
}
- close_consumer_sockets();
-
/*
* We do NOT rmdir rundir because there are other processes
* using it, for instance lttng-relayd, which can start in
run_as_destroy_worker();
}
-/*
- * Setup necessary data for kernel tracer action.
- */
-static int init_kernel_tracer(void)
-{
- int ret;
-
- /* Modprobe lttng kernel modules */
- ret = modprobe_lttng_control();
- if (ret < 0) {
- goto error;
- }
-
- /* Open debugfs lttng */
- kernel_tracer_fd = open(module_proc_lttng, O_RDWR);
- if (kernel_tracer_fd < 0) {
- DBG("Failed to open %s", module_proc_lttng);
- goto error_open;
- }
-
- /* Validate kernel version */
- ret = kernel_validate_version(kernel_tracer_fd, &kernel_tracer_version,
- &kernel_tracer_abi_version);
- if (ret < 0) {
- goto error_version;
- }
-
- ret = modprobe_lttng_data();
- if (ret < 0) {
- 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;
-
-error_version:
- modprobe_remove_lttng_control();
- ret = close(kernel_tracer_fd);
- if (ret) {
- PERROR("close");
- }
- kernel_tracer_fd = -1;
- return LTTNG_ERR_KERN_VERSION;
-
-error_modules:
- ret = close(kernel_tracer_fd);
- if (ret) {
- PERROR("close");
- }
-
-error_open:
- modprobe_remove_lttng_control();
-
-error:
- WARN("No kernel tracer available");
- kernel_tracer_fd = -1;
- if (!is_root) {
- return LTTNG_ERR_NEED_ROOT_SESSIOND;
- } else {
- return LTTNG_ERR_KERN_NA;
- }
-}
-
static int string_match(const char *str1, const char *str2)
{
return (str1 && str2) && !strcmp(str1, str2);
}
exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
} else if (string_match(optname, "version") || opt == 'V') {
- fprintf(stdout, "%s\n", VERSION);
- exit(EXIT_SUCCESS);
+ opt_print_version = 1;
} else if (string_match(optname, "sig-parent") || opt == 'S') {
config.sig_parent = true;
} else if (string_match(optname, "kconsumerd-err-sock")) {
WARN("Getting '%s' argument from setuid/setgid binary refused for security reasons.",
"-l, --load");
} else {
- config_string_set(&config.load_session_path, strdup(arg));
+ config_string_set(&config.load_session_path, strdup(arg));
if (!config.load_session_path.value) {
PERROR("strdup");
ret = -ENOMEM;
return ret;
}
+static void print_version(void) {
+ fprintf(stdout, "%s\n", VERSION);
+}
+
/*
* daemon configuration loading and argument parsing
*/
*/
static int create_lockfile(void)
{
- return utils_create_lock_file(config.lock_file_path.value);
+ return utils_create_lock_file(config.lock_file_path.value);
}
/*
int ret;
gid_t gid;
- gid = utils_get_group_id(config.tracing_group_name.value);
+ ret = utils_get_group_id(config.tracing_group_name.value, true, &gid);
+ if (ret) {
+ /* Default to root group. */
+ gid = 0;
+ }
/* Set lttng run dir */
ret = chown(rundir, 0, gid);
goto error;
}
if (is_root) {
- ret = chown(path, 0, utils_get_group_id(config.tracing_group_name.value));
+ gid_t gid;
+
+ ret = utils_get_group_id(config.tracing_group_name.value, true,
+ &gid);
+ if (ret) {
+ /* Default to root group. */
+ gid = 0;
+ }
+
+ ret = chown(path, 0, gid);
if (ret < 0) {
ERR("Unable to set group on %s", path);
PERROR("chown");
static int write_pidfile(void)
{
- return utils_create_pid_file(getpid(), config.pid_file_path.value);
+ return utils_create_pid_file(getpid(), config.pid_file_path.value);
}
static int set_clock_plugin_env(void)
goto end;
}
- ret = asprintf(&env_value, "LTTNG_UST_CLOCK_PLUGIN=%s",
+ ret = asprintf(&env_value, "LTTNG_UST_CLOCK_PLUGIN=%s",
config.lttng_ust_clock_plugin.value);
if (ret < 0) {
PERROR("asprintf");
goto unlock_session;
}
(void) cmd_stop_trace(session);
- (void) cmd_destroy_session(session,
- notification_thread_handle);
+ (void) cmd_destroy_session(session, notification_thread_handle,
+ NULL);
unlock_session:
session_unlock(session);
session_put(session);
DBG("Destruction of all sessions completed");
}
+static int run_as_worker_post_fork_cleanup(void *data)
+{
+ struct sessiond_config *sessiond_config = data;
+
+ sessiond_config_fini(sessiond_config);
+ return 0;
+}
+
+static int launch_run_as_worker(const char *procname)
+{
+ /*
+ * Clean-up before forking the run-as worker. Any dynamically
+ * allocated memory of which the worker is not aware will
+ * be leaked as the process forks a run-as worker (and performs
+ * no exec*()). The same would apply to any opened fd.
+ */
+ return run_as_create_worker(procname, run_as_worker_post_fork_cleanup,
+ &config);
+}
+
+static void sessiond_uuid_log(void)
+{
+ char uuid_str[LTTNG_UUID_STR_LEN];
+
+ lttng_uuid_to_str(sessiond_uuid, uuid_str);
+ DBG("Starting lttng-sessiond {%s}", uuid_str);
+}
+
/*
* main
*/
struct rotation_thread_timer_queue *rotation_timer_queue = NULL;
struct lttng_thread *client_thread = NULL;
struct lttng_thread *notification_thread = NULL;
+ struct lttng_thread *register_apps_thread = NULL;
+ logger_set_thread_name("Main", false);
init_kernel_workarounds();
rcu_register_thread();
set_clock_plugin_env();
sessiond_config_log(&config);
+ sessiond_uuid_log();
+
+ if (opt_print_version) {
+ print_version();
+ retval = 0;
+ goto exit_options;
+ }
if (create_lttng_rundir()) {
retval = -1;
}
}
- if (run_as_create_worker(argv[0]) < 0) {
+ if (launch_run_as_worker(argv[0]) < 0) {
goto exit_create_run_as_worker_cleanup;
}
if (!health_sessiond) {
PERROR("health_app_create error");
retval = -1;
- goto exit_health_sessiond_cleanup;
+ goto stop_threads;
}
/* Create thread to clean up RCU hash tables */
ht_cleanup_thread = launch_ht_cleanup_thread();
if (!ht_cleanup_thread) {
retval = -1;
- goto exit_ht_cleanup;
+ goto stop_threads;
}
/* Create thread quit pipe */
if (sessiond_init_thread_quit_pipe()) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/* Check if daemon is UID = 0 */
if (!kernel_channel_monitor_pipe) {
ERR("Failed to create kernel consumer channel monitor pipe");
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
kconsumer_data.channel_monitor_pipe =
lttng_pipe_release_writefd(
kernel_channel_monitor_pipe);
if (kconsumer_data.channel_monitor_pipe < 0) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
}
if (!ust32_channel_monitor_pipe) {
ERR("Failed to create 32-bit user space consumer channel monitor pipe");
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
ustconsumer32_data.channel_monitor_pipe = lttng_pipe_release_writefd(
ust32_channel_monitor_pipe);
if (ustconsumer32_data.channel_monitor_pipe < 0) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/*
rotation_timer_queue = rotation_thread_timer_queue_create();
if (!rotation_timer_queue) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
timer_thread_parameters.rotation_thread_job_queue =
rotation_timer_queue;
if (!ust64_channel_monitor_pipe) {
ERR("Failed to create 64-bit user space consumer channel monitor pipe");
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
ustconsumer64_data.channel_monitor_pipe = lttng_pipe_release_writefd(
ust64_channel_monitor_pipe);
if (ustconsumer64_data.channel_monitor_pipe < 0) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/*
if (ust_app_ht_alloc()) {
ERR("Failed to allocate UST app hash table");
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/*
if (agent_app_ht_alloc()) {
ERR("Failed to allocate Agent app hash table");
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/*
if (is_root) {
if (set_consumer_sockets(&kconsumer_data)) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/* Setup kernel tracer */
if (!config.no_kernel) {
init_kernel_tracer();
- if (kernel_tracer_fd >= 0) {
- ret = syscall_init_table();
- if (ret < 0) {
- ERR("Unable to populate syscall table. "
- "Syscall tracing won't work "
- "for this session daemon.");
- }
- }
}
/* Set ulimit for open files */
if (set_consumer_sockets(&ustconsumer64_data)) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
if (set_consumer_sockets(&ustconsumer32_data)) {
retval = -1;
- goto exit_init_data;
- }
-
- /* Set credentials to socket */
- if (is_root && set_permissions(config.rundir.value)) {
- retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/* Get parent pid if -S, --sig-parent is specified. */
if (is_root && !config.no_kernel) {
if (utils_create_pipe_cloexec(kernel_poll_pipe)) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
}
/* Setup the thread apps communication pipe. */
if (utils_create_pipe_cloexec(apps_cmd_pipe)) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/* Setup the thread apps notify communication pipe. */
if (utils_create_pipe_cloexec(apps_cmd_notify_pipe)) {
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/* Initialize global buffer per UID and PID registry. */
if (ret) {
ERR("Error in write_pidfile");
retval = -1;
- goto exit_init_data;
+ goto stop_threads;
}
/* Initialize communication library */
/* Create health-check thread. */
if (!launch_health_management_thread()) {
retval = -1;
- goto exit_health;
+ goto stop_threads;
}
/* notification_thread_data acquires the pipes' read side. */
if (!notification_thread_handle) {
retval = -1;
ERR("Failed to create notification thread shared data");
- goto exit_notification;
+ goto stop_threads;
}
/* Create notification thread. */
notification_thread_handle);
if (!notification_thread) {
retval = -1;
- goto exit_notification;
+ goto stop_threads;
}
/* Create timer thread. */
if (!launch_timer_thread(&timer_thread_parameters)) {
retval = -1;
- goto exit_notification;
+ goto stop_threads;
}
/* rotation_thread_data acquires the pipes' read side. */
retval = -1;
ERR("Failed to create rotation thread shared data");
stop_threads();
- goto exit_rotation;
+ goto stop_threads;
}
/* Create rotation thread. */
if (!launch_rotation_thread(rotation_thread_handle)) {
retval = -1;
- goto exit_rotation;
+ goto stop_threads;
}
/* Create thread to manage the client socket */
client_thread = launch_client_thread();
if (!client_thread) {
retval = -1;
- goto exit_client;
+ goto stop_threads;
+ }
+
+ /* Set credentials of the client socket and rundir */
+ if (is_root && set_permissions(config.rundir.value)) {
+ retval = -1;
+ goto stop_threads;
}
if (!launch_ust_dispatch_thread(&ust_cmd_queue, apps_cmd_pipe[1],
apps_cmd_notify_pipe[1])) {
retval = -1;
- goto exit_dispatch;
+ goto stop_threads;
}
/* Create thread to manage application registration. */
- if (!launch_application_registration_thread(&ust_cmd_queue)) {
+ register_apps_thread = launch_application_registration_thread(
+ &ust_cmd_queue);
+ if (!register_apps_thread) {
retval = -1;
- goto exit_reg_apps;
+ goto stop_threads;
}
/* Create thread to manage application socket */
if (!launch_application_management_thread(apps_cmd_pipe[0])) {
retval = -1;
- goto exit_apps;
+ goto stop_threads;
}
/* Create thread to manage application notify socket */
if (!launch_application_notification_thread(apps_cmd_notify_pipe[0])) {
retval = -1;
- goto exit_apps_notify;
+ goto stop_threads;
}
/* Create agent management thread. */
if (!launch_agent_management_thread()) {
retval = -1;
- goto exit_agent_reg;
+ goto stop_threads;
}
/* Don't start this thread if kernel tracing is not requested nor root */
/* Create kernel thread to manage kernel event */
if (!launch_kernel_management_thread(kernel_poll_pipe[0])) {
retval = -1;
- goto exit_kernel;
+ goto stop_threads;
}
}
if (ret) {
ERR("Session load failed: %s", error_get_str(ret));
retval = -1;
- goto exit_load_session;
+ goto stop_threads;
}
/* Initialization completed. */
*/
/* Initiate teardown once activity occurs on the quit pipe. */
- sessiond_wait_for_quit_pipe(-1U);
+ sessiond_wait_for_quit_pipe(-1);
+stop_threads:
/*
* Ensure that the client thread is no longer accepting new commands,
* which could cause new sessions to be created.
*/
- if (!lttng_thread_shutdown(client_thread)) {
- ERR("Failed to shutdown the client thread, continuing teardown");
+ if (client_thread) {
+ lttng_thread_shutdown(client_thread);
lttng_thread_put(client_thread);
- client_thread = NULL;
}
destroy_all_sessions_and_wait();
-exit_load_session:
-exit_kernel:
-exit_agent_reg:
-exit_apps_notify:
-exit_apps:
-exit_reg_apps:
-exit_dispatch:
-exit_client:
-exit_rotation:
-exit_notification:
- lttng_thread_list_shutdown_orphans();
-exit_health:
-exit_init_data:
- if (client_thread) {
- lttng_thread_put(client_thread);
+
+ if (register_apps_thread) {
+ lttng_thread_shutdown(register_apps_thread);
+ lttng_thread_put(register_apps_thread);
}
+ lttng_thread_list_shutdown_orphans();
/*
* Wait for all pending call_rcu work to complete before tearing
lttng_pipe_destroy(ust32_channel_monitor_pipe);
lttng_pipe_destroy(ust64_channel_monitor_pipe);
lttng_pipe_destroy(kernel_channel_monitor_pipe);
-exit_ht_cleanup:
- health_app_destroy(health_sessiond);
-exit_health_sessiond_cleanup:
+ if (health_sessiond) {
+ health_app_destroy(health_sessiond);
+ }
exit_create_run_as_worker_cleanup:
-
exit_options:
sessiond_cleanup_lock_file();
sessiond_cleanup_options();