Fix: Unchecked strdup return values in set_option
[lttng-tools.git] / src / bin / lttng-sessiond / main.c
index 052e32e0c32ec2fb8bfe2a17e71afa0487ebf868..548cc43095b633bb09528085dfb878a5e99578f6 100644 (file)
@@ -69,6 +69,7 @@
 #include "ust-thread.h"
 #include "jul-thread.h"
 #include "save.h"
+#include "load-session-thread.h"
 
 #define CONSUMERD_FILE "lttng-consumerd"
 
@@ -80,6 +81,7 @@ static int opt_sig_parent;
 static int opt_verbose_consumer;
 static int opt_daemon, opt_background;
 static int opt_no_kernel;
+static char *opt_load_session_path;
 static pid_t ppid;          /* Parent PID for --sig-parent option */
 static pid_t child_ppid;    /* Internal parent PID use with daemonize. */
 static char *rundir;
@@ -152,6 +154,8 @@ static const struct option long_options[] = {
        { "pidfile", 1, 0, 'p' },
        { "jul-tcp-port", 1, 0, 'J' },
        { "config", 1, 0, 'f' },
+       { "load", 1, 0, 'l' },
+       { "kmod-probes", 1, 0, 'P' },
        { NULL, 0, 0, 0 }
 };
 
@@ -200,6 +204,7 @@ static pthread_t dispatch_thread;
 static pthread_t health_thread;
 static pthread_t ht_cleanup_thread;
 static pthread_t jul_reg_thread;
+static pthread_t load_session_thread;
 
 /*
  * UST registration command queue. This queue is tied with a futex and uses a N
@@ -291,17 +296,20 @@ int is_root;                      /* Set to 1 if the daemon is running as root */
 
 const char * const config_section_name = "sessiond";
 
+/* Load session thread information to operate. */
+struct load_session_thread_data *load_info;
+
 /*
  * Whether sessiond is ready for commands/health check requests.
  * NR_LTTNG_SESSIOND_READY must match the number of calls to
- * lttng_sessiond_notify_ready().
+ * sessiond_notify_ready().
  */
-#define NR_LTTNG_SESSIOND_READY                2
+#define NR_LTTNG_SESSIOND_READY                3
 int lttng_sessiond_ready = NR_LTTNG_SESSIOND_READY;
 
 /* Notify parents that we are ready for cmd and health check */
-static
-void lttng_sessiond_notify_ready(void)
+LTTNG_HIDDEN
+void sessiond_notify_ready(void)
 {
        if (uatomic_sub_return(&lttng_sessiond_ready, 1) == 0) {
                /*
@@ -647,6 +655,15 @@ static void cleanup(void)
                free(opt_pidfile);
        }
 
+       if (opt_load_session_path) {
+               free(opt_load_session_path);
+       }
+
+       if (load_info) {
+               load_session_destroy_data(load_info);
+               free(load_info);
+       }
+
        /* <fun> */
        DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm"
                        "Matthew, BEET driven development works!%c[%dm",
@@ -2805,6 +2822,38 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
                break;
        }
 
+       /*
+        * Commands that need a valid session but should NOT create one if none
+        * exists. Instead of creating one and destroying it when the command is
+        * handled, process that right before so we save some round trip in useless
+        * code path.
+        */
+       switch (cmd_ctx->lsm->cmd_type) {
+       case LTTNG_DISABLE_CHANNEL:
+       case LTTNG_DISABLE_EVENT:
+       case LTTNG_DISABLE_ALL_EVENT:
+               switch (cmd_ctx->lsm->domain.type) {
+               case LTTNG_DOMAIN_KERNEL:
+                       if (!cmd_ctx->session->kernel_session) {
+                               ret = LTTNG_ERR_NO_CHANNEL;
+                               goto error;
+                       }
+                       break;
+               case LTTNG_DOMAIN_JUL:
+               case LTTNG_DOMAIN_UST:
+                       if (!cmd_ctx->session->ust_session) {
+                               ret = LTTNG_ERR_NO_CHANNEL;
+                               goto error;
+                       }
+                       break;
+               default:
+                       ret = LTTNG_ERR_UNKNOWN_DOMAIN;
+                       goto error;
+               }
+       default:
+               break;
+       }
+
        if (!need_domain) {
                goto skip_domain;
        }
@@ -3723,7 +3772,7 @@ static void *thread_manage_health(void *data)
                goto error;
        }
 
-       lttng_sessiond_notify_ready();
+       sessiond_notify_ready();
 
        while (1) {
                DBG("Health check ready");
@@ -3875,7 +3924,12 @@ static void *thread_manage_clients(void *data)
                goto error;
        }
 
-       lttng_sessiond_notify_ready();
+       sessiond_notify_ready();
+       ret = sem_post(&load_info->message_thread_ready);
+       if (ret) {
+               PERROR("sem_post message_thread_ready");
+               goto error;
+       }
 
        /* This testpoint is after we signal readiness to the parent. */
        if (testpoint(sessiond_thread_manage_clients)) {
@@ -4110,6 +4164,8 @@ static void usage(void)
        fprintf(stderr, "      --no-kernel                    Disable kernel tracer\n");
        fprintf(stderr, "      --jul-tcp-port                 JUL application registration TCP port\n");
        fprintf(stderr, "  -f  --config                       Load daemon configuration file\n");
+       fprintf(stderr, "  -l  --load PATH                    Load session configuration\n");
+       fprintf(stderr, "      --kmod-probes                  Specify kernel module probes to load\n");
 }
 
 /*
@@ -4143,6 +4199,10 @@ static int set_option(int opt, const char *arg, const char *optname)
                break;
        case 'g':
                tracing_group_name = strdup(arg);
+               if (!tracing_group_name) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
                break;
        case 'h':
                usage();
@@ -4182,7 +4242,10 @@ static int set_option(int opt, const char *arg, const char *optname)
                if (arg) {
                        lttng_opt_verbose = config_parse_value(arg);
                } else {
-                       lttng_opt_verbose += 1;
+                       /* Only 3 level of verbosity (-vvv). */
+                       if (lttng_opt_verbose < 3) {
+                               lttng_opt_verbose += 1;
+                       }
                }
                break;
        case 'Z':
@@ -4194,22 +4257,42 @@ static int set_option(int opt, const char *arg, const char *optname)
                break;
        case 'u':
                consumerd32_bin = strdup(arg);
+               if (!consumerd32_bin) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
                consumerd32_bin_override = 1;
                break;
        case 'U':
                consumerd32_libdir = strdup(arg);
+               if (!consumerd32_libdir) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
                consumerd32_libdir_override = 1;
                break;
        case 't':
                consumerd64_bin = strdup(arg);
+               if (!consumerd64_bin) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
                consumerd64_bin_override = 1;
                break;
        case 'T':
                consumerd64_libdir = strdup(arg);
+               if (!consumerd64_libdir) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
                consumerd64_libdir_override = 1;
                break;
        case 'p':
                opt_pidfile = strdup(arg);
+               if (!opt_pidfile) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
                break;
        case 'J': /* JUL TCP port. */
        {
@@ -4229,6 +4312,23 @@ static int set_option(int opt, const char *arg, const char *optname)
                DBG3("JUL TCP port set to non default: %u", jul_tcp_port);
                break;
        }
+       case 'l':
+               opt_load_session_path = strdup(arg);
+               if (!opt_load_session_path) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
+               break;
+       case 'P': /* probe modules list */
+               kmod_probes_list = strdup(arg);
+               if (!kmod_probes_list) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
+               break;
+       case 'f':
+               /* This is handled in set_options() thus silent break. */
+               break;
        default:
                /* Unknown option or other error.
                 * Error is printed by getopt, just return */
@@ -4756,6 +4856,35 @@ error:
        return;
 }
 
+/*
+ * Start the load session thread and dettach from it so the main thread can
+ * continue. This does not return a value since whatever the outcome, the main
+ * thread will continue.
+ */
+static void start_load_session_thread(void)
+{
+       int ret;
+
+       /* Create session loading thread. */
+       ret = pthread_create(&load_session_thread, NULL, thread_load_session,
+                       load_info);
+       if (ret != 0) {
+               PERROR("pthread_create load_session_thread");
+               goto error_create;
+       }
+
+       ret = pthread_detach(load_session_thread);
+       if (ret != 0) {
+               PERROR("pthread_detach load_session_thread");
+       }
+
+       /* Everything went well so don't cleanup anything. */
+
+error_create:
+       /* The cleanup() function will destroy the load_info data. */
+       return;
+}
+
 /*
  * main
  */
@@ -5065,6 +5194,11 @@ int main(int argc, char **argv)
        /* This is to get the TCP timeout value. */
        lttcomm_inet_init();
 
+       if (load_session_init_data(&load_info) < 0) {
+               goto exit;
+       }
+       load_info->path = opt_load_session_path;
+
        /*
         * Initialize the health check subsystem. This call should set the
         * appropriate time values.
@@ -5127,7 +5261,7 @@ int main(int argc, char **argv)
        ret = pthread_create(&apps_notify_thread, NULL,
                        ust_thread_manage_notify, (void *) NULL);
        if (ret != 0) {
-               PERROR("pthread_create apps");
+               PERROR("pthread_create notify");
                goto exit_apps_notify;
        }
 
@@ -5135,7 +5269,7 @@ int main(int argc, char **argv)
        ret = pthread_create(&jul_reg_thread, NULL,
                        jul_thread_manage_registration, (void *) NULL);
        if (ret != 0) {
-               PERROR("pthread_create apps");
+               PERROR("pthread_create JUL");
                goto exit_jul_reg;
        }
 
@@ -5148,7 +5282,12 @@ int main(int argc, char **argv)
                        PERROR("pthread_create kernel");
                        goto exit_kernel;
                }
+       }
 
+       /* Load possible session(s). */
+       start_load_session_thread();
+
+       if (is_root && !opt_no_kernel) {
                ret = pthread_join(kernel_thread, &status);
                if (ret != 0) {
                        PERROR("pthread_join");
This page took 0.027442 seconds and 4 git commands to generate.