/*
- * 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 per-event notifier domain agents");
+ agent_by_event_notifier_domain_ht_destroy();
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);
}
/*
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 void unregister_all_triggers(void)
+{
+ enum lttng_error_code ret_code;
+ enum lttng_trigger_status trigger_status;
+ struct lttng_triggers *triggers = NULL;
+ unsigned int trigger_count, i;
+ const struct lttng_credentials creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(0),
+ };
+
+ DBG("Unregistering all triggers");
+
+ /*
+ * List all triggers as "root" since we wish to unregister all triggers.
+ */
+ ret_code = notification_thread_command_list_triggers(
+ notification_thread_handle, creds.uid.value, &triggers);
+ if (ret_code != LTTNG_OK) {
+ ERR("Failed to list triggers while unregistering all triggers");
+ goto end;
+ }
+
+ trigger_status = lttng_triggers_get_count(triggers, &trigger_count);
+ assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+ for (i = 0; i < trigger_count; i++) {
+ enum lttng_error_code ret_code;
+ uid_t trigger_owner;
+ const char *trigger_name;
+ const struct lttng_trigger *trigger =
+ lttng_triggers_get_at_index(triggers, i);
+
+ assert(trigger);
+
+ trigger_status = lttng_trigger_get_owner_uid(
+ trigger, &trigger_owner);
+ assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+ trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
+ assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+ DBG("Unregistering trigger: trigger owner uid = %d, trigger name = '%s'",
+ (int) trigger_owner, trigger_name);
+
+ ret_code = cmd_unregister_trigger(
+ &creds, trigger, notification_thread_handle);
+ if (ret_code != LTTNG_OK) {
+ ERR("Failed to unregister trigger: trigger owner uid = %d, trigger name = '%s', error: '%s'",
+ (int) trigger_owner, trigger_name,
+ lttng_strerror(-ret_code));
+ /* Continue to unregister the remaining triggers. */
+ }
+ }
+end:
+ lttng_triggers_destroy(triggers);
+}
+
static int run_as_worker_post_fork_cleanup(void *data)
{
struct sessiond_config *sessiond_config = data;
&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 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;
goto stop_threads;
}
+ if (agent_by_event_notifier_domain_ht_create()) {
+ ERR("Failed to allocate per-event notifier domain agent hash table");
+ retval = -1;
+ goto stop_threads;
+ }
/*
* These actions must be executed as root. We do that *after* setting up
* the sockets path because we MUST make the check for another daemon using
/* 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 */
retval = -1;
goto stop_threads;
}
+
+ if (kernel_get_notification_fd() >= 0) {
+ ret = notification_thread_command_add_tracer_event_source(
+ notification_thread_handle,
+ kernel_get_notification_fd(),
+ LTTNG_DOMAIN_KERNEL);
+ if (ret != LTTNG_OK) {
+ ERR("Failed to add kernel trigger event source to notification thread");
+ retval = -1;
+ goto stop_threads;
+ }
+ }
}
/* Load sessions. */
*/
/* Initiate teardown once activity occurs on the quit pipe. */
- sessiond_wait_for_quit_pipe(-1U);
+ sessiond_wait_for_quit_pipe(-1);
stop_threads:
/*
destroy_all_sessions_and_wait();
+ /*
+ * At this point no new trigger can be registered (no sessions are
+ * running/rotating) and clients can't connect to the session daemon
+ * anymore. Unregister all triggers.
+ */
+ unregister_all_triggers();
+
if (register_apps_thread) {
lttng_thread_shutdown(register_apps_thread);
lttng_thread_put(register_apps_thread);
rcu_thread_online();
sessiond_cleanup();
+ /*
+ * Wait for all pending call_rcu work to complete tearing shutting down
+ * the notification thread. This call_rcu work includes shutting down
+ * UST apps and event notifier pipes.
+ */
+ rcu_barrier();
+
if (notification_thread) {
lttng_thread_shutdown(notification_thread);
lttng_thread_put(notification_thread);
lttng_pipe_destroy(ust64_channel_monitor_pipe);
lttng_pipe_destroy(kernel_channel_monitor_pipe);
- health_app_destroy(health_sessiond);
+ if (health_sessiond) {
+ health_app_destroy(health_sessiond);
+ }
exit_create_run_as_worker_cleanup:
exit_options:
sessiond_cleanup_lock_file();