Fix: leak of sessiond configuration on launch of run-as worker
[lttng-tools.git] / src / bin / lttng-sessiond / main.c
index 1fbfb1b0549383cd77e5334aad25338320cb6d56..24855b9767632bc1584316b0b0c80362d870c2e5 100644 (file)
@@ -69,7 +69,7 @@
 #include "fd-limit.h"
 #include "health-sessiond.h"
 #include "testpoint.h"
-#include "ust-thread.h"
+#include "notify-apps.h"
 #include "agent-thread.h"
 #include "save.h"
 #include "notification-thread.h"
@@ -1336,6 +1336,26 @@ static void destroy_all_sessions_and_wait(void)
        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);
+}
+
 /*
  * main
  */
@@ -1353,6 +1373,8 @@ int main(int argc, char **argv)
        /* Queue of rotation jobs populated by the sessiond-timer. */
        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;
 
        init_kernel_workarounds();
 
@@ -1467,7 +1489,7 @@ int main(int argc, char **argv)
                }
        }
 
-       if (run_as_create_worker(argv[0]) < 0) {
+       if (launch_run_as_worker(argv[0]) < 0) {
                goto exit_create_run_as_worker_cleanup;
        }
 
@@ -1484,20 +1506,20 @@ int main(int argc, char **argv)
        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 */
@@ -1509,14 +1531,14 @@ int main(int argc, char **argv)
                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;
                }
        }
 
@@ -1528,13 +1550,13 @@ int main(int argc, char **argv)
        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;
        }
 
        /*
@@ -1545,7 +1567,7 @@ int main(int argc, char **argv)
        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;
@@ -1554,13 +1576,13 @@ int main(int argc, char **argv)
        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;
        }
 
        /*
@@ -1570,7 +1592,7 @@ int main(int argc, char **argv)
        if (ust_app_ht_alloc()) {
                ERR("Failed to allocate UST app hash table");
                retval = -1;
-               goto exit_init_data;
+               goto stop_threads;
        }
 
        /*
@@ -1580,7 +1602,7 @@ int main(int argc, char **argv)
        if (agent_app_ht_alloc()) {
                ERR("Failed to allocate Agent app hash table");
                retval = -1;
-               goto exit_init_data;
+               goto stop_threads;
        }
 
        /*
@@ -1592,7 +1614,7 @@ int main(int argc, char **argv)
        if (is_root) {
                if (set_consumer_sockets(&kconsumer_data)) {
                        retval = -1;
-                       goto exit_init_data;
+                       goto stop_threads;
                }
 
                /* Setup kernel tracer */
@@ -1616,18 +1638,12 @@ int main(int argc, char **argv)
 
        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. */
@@ -1639,20 +1655,20 @@ int main(int argc, char **argv)
        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. */
@@ -1676,7 +1692,7 @@ int main(int argc, char **argv)
        if (ret) {
                ERR("Error in write_pidfile");
                retval = -1;
-               goto exit_init_data;
+               goto stop_threads;
        }
 
        /* Initialize communication library */
@@ -1687,7 +1703,7 @@ int main(int argc, char **argv)
        /* 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. */
@@ -1698,19 +1714,21 @@ int main(int argc, char **argv)
        if (!notification_thread_handle) {
                retval = -1;
                ERR("Failed to create notification thread shared data");
-               goto exit_notification;
+               goto stop_threads;
        }
 
        /* Create notification thread. */
-       if (!launch_notification_thread(notification_thread_handle)) {
+       notification_thread = launch_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. */
@@ -1721,50 +1739,58 @@ int main(int argc, char **argv)
                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 */
@@ -1772,7 +1798,7 @@ int main(int argc, char **argv)
                /* Create kernel thread to manage kernel event */
                if (!launch_kernel_management_thread(kernel_poll_pipe[0])) {
                        retval = -1;
-                       goto exit_kernel;
+                       goto stop_threads;
                }
        }
 
@@ -1782,7 +1808,7 @@ int main(int argc, char **argv)
        if (ret) {
                ERR("Session load failed: %s", error_get_str(ret));
                retval = -1;
-               goto exit_load_session;
+               goto stop_threads;
        }
 
        /* Initialization completed. */
@@ -1796,33 +1822,23 @@ int main(int argc, char **argv)
        /* Initiate teardown once activity occurs on the quit pipe. */
        sessiond_wait_for_quit_pipe(-1U);
 
+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
@@ -1837,6 +1853,11 @@ exit_init_data:
        rcu_thread_online();
        sessiond_cleanup();
 
+       if (notification_thread) {
+               lttng_thread_shutdown(notification_thread);
+               lttng_thread_put(notification_thread);
+       }
+
        /*
         * Ensure all prior call_rcu are done. call_rcu callbacks may push
         * hash tables to the ht_cleanup thread. Therefore, we ensure that
@@ -1872,12 +1893,9 @@ exit_init_data:
        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:
 exit_create_run_as_worker_cleanup:
-
 exit_options:
        sessiond_cleanup_lock_file();
        sessiond_cleanup_options();
This page took 0.029539 seconds and 5 git commands to generate.