Cleanup: Move `create_posix_shm()` to common/shm.c
[lttng-tools.git] / src / bin / lttng-sessiond / main.c
index 57324820bd6aa2c3e09da7f3d0106c8f80c5b89d..40a418d0cfd0a79c453a8637df7322e15aca286e 100644 (file)
@@ -1,20 +1,10 @@
 /*
- * 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
@@ -61,9 +51,7 @@
 #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"
@@ -75,7 +63,6 @@
 #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"
@@ -97,6 +84,7 @@ NULL
 
 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;
@@ -155,8 +143,6 @@ static int apps_cmd_notify_pipe[2] = { -1, -1 };
  */
 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.
  */
@@ -327,32 +313,25 @@ static void sessiond_cleanup(void)
 
        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
@@ -372,81 +351,6 @@ static void sessiond_cleanup_options(void)
        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);
@@ -522,8 +426,7 @@ static int set_option(int opt, const char *arg, const char *optname)
                }
                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")) {
@@ -756,7 +659,7 @@ static int set_option(int opt, const char *arg, const char *optname)
                        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;
@@ -878,6 +781,10 @@ end:
        return ret;
 }
 
+static void print_version(void) {
+       fprintf(stdout, "%s\n", VERSION);
+}
+
 /*
  * daemon configuration loading and argument parsing
  */
@@ -964,7 +871,7 @@ end:
  */
 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);
 }
 
 /*
@@ -1278,7 +1185,7 @@ static void set_ulimit(void)
 
 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)
@@ -1290,7 +1197,7 @@ 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");
@@ -1335,8 +1242,8 @@ static void destroy_all_sessions_and_wait(void)
                        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);
@@ -1349,6 +1256,63 @@ static void destroy_all_sessions_and_wait(void)
        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;
@@ -1369,6 +1333,14 @@ static int launch_run_as_worker(const char *procname)
                        &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
  */
@@ -1389,6 +1361,7 @@ int main(int argc, char **argv)
        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();
@@ -1465,6 +1438,13 @@ int main(int argc, char **argv)
        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;
@@ -1618,6 +1598,11 @@ int main(int argc, char **argv)
                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
@@ -1633,14 +1618,6 @@ int main(int argc, char **argv)
                /* 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 */
@@ -1813,6 +1790,18 @@ int main(int argc, char **argv)
                        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. */
@@ -1833,7 +1822,7 @@ int main(int argc, char **argv)
         */
 
        /* Initiate teardown once activity occurs on the quit pipe. */
-       sessiond_wait_for_quit_pipe(-1U);
+       sessiond_wait_for_quit_pipe(-1);
 
 stop_threads:
        /*
@@ -1847,6 +1836,13 @@ 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);
@@ -1866,6 +1862,13 @@ stop_threads:
        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);
@@ -1907,7 +1910,9 @@ stop_threads:
        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();
This page took 0.028081 seconds and 4 git commands to generate.