Fix: Handle empty daemon configuration file lines
[lttng-tools.git] / src / bin / lttng-sessiond / main.c
index fac06e0f75c62512e67ea2e87f2b469a5b2a1d90..3e04f963329e6603c859164f1ee4ff4207a8e118 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <getopt.h>
 #include <grp.h>
 #include <limits.h>
@@ -70,6 +71,7 @@
 #include "agent-thread.h"
 #include "save.h"
 #include "load-session-thread.h"
+#include "syscall.h"
 
 #define CONSUMERD_FILE "lttng-consumerd"
 
@@ -157,6 +159,7 @@ static const struct option long_options[] = {
        { "config", 1, 0, 'f' },
        { "load", 1, 0, 'l' },
        { "kmod-probes", 1, 0, 'P' },
+       { "extra-kmod-probes", 1, 0, 'e' },
        { NULL, 0, 0, 0 }
 };
 
@@ -641,6 +644,7 @@ static void cleanup(void)
                }
                DBG("Unloading kernel modules");
                modprobe_remove_lttng_all();
+               free(syscall_table);
        }
 
        close_consumer_sockets();
@@ -1113,7 +1117,7 @@ static void signal_consumer_condition(struct consumer_data *data, int state)
  */
 static void *thread_manage_consumer(void *data)
 {
-       int sock = -1, i, ret, pollfd, err = -1;
+       int sock = -1, i, ret, pollfd, err = -1, should_quit = 0;
        uint32_t revents, nb_fd;
        enum lttcomm_return_code code;
        struct lttng_poll_event events;
@@ -1271,6 +1275,15 @@ restart:
        /* Infinite blocking call, waiting for transmission */
 restart_poll:
        while (1) {
+               health_code_update();
+
+               /* Exit the thread because the thread quit pipe has been triggered. */
+               if (should_quit) {
+                       /* Not a health error. */
+                       err = 0;
+                       goto exit;
+               }
+
                health_poll_entry();
                ret = lttng_poll_wait(&events, -1);
                health_poll_exit();
@@ -1293,12 +1306,12 @@ restart_poll:
 
                        health_code_update();
 
-                       /* Thread quit pipe has been closed. Killing thread. */
-                       ret = sessiond_check_thread_quit_pipe(pollfd, revents);
-                       if (ret) {
-                               err = 0;
-                               goto exit;
-                       }
+                       /*
+                        * Thread quit pipe has been triggered, flag that we should stop
+                        * but continue the current loop to handle potential data from
+                        * consumer.
+                        */
+                       should_quit = sessiond_check_thread_quit_pipe(pollfd, revents);
 
                        if (pollfd == sock) {
                                /* Event on the consumerd socket */
@@ -1327,11 +1340,8 @@ restart_poll:
                                        ERR("Handling metadata request");
                                        goto error;
                                }
-                               break;
-                       } else {
-                               ERR("Unknown pollfd");
-                               goto error;
                        }
+                       /* No need for an else branch all FDs are tested prior. */
                }
                health_code_update();
        }
@@ -2593,6 +2603,8 @@ static int copy_session_consumer(int domain, struct ltt_session *session)
                dir_name = DEFAULT_KERNEL_TRACE_DIR;
                break;
        case LTTNG_DOMAIN_JUL:
+       case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_UST:
                DBG3("Copying tracing session consumer output in UST session");
                if (session->ust_session->consumer) {
@@ -2637,6 +2649,8 @@ static int create_ust_session(struct ltt_session *session,
 
        switch (domain->type) {
        case LTTNG_DOMAIN_JUL:
+       case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_UST:
                break;
        default:
@@ -2823,6 +2837,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
        case LTTNG_LIST_DOMAINS:
        case LTTNG_LIST_CHANNELS:
        case LTTNG_LIST_EVENTS:
+       case LTTNG_LIST_SYSCALLS:
                break;
        default:
                /* Setup lttng message with no payload */
@@ -2841,6 +2856,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
        case LTTNG_CALIBRATE:
        case LTTNG_LIST_SESSIONS:
        case LTTNG_LIST_TRACEPOINTS:
+       case LTTNG_LIST_SYSCALLS:
        case LTTNG_LIST_TRACEPOINT_FIELDS:
        case LTTNG_SAVE_SESSION:
                need_tracing_session = 0;
@@ -2873,7 +2889,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
        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) {
@@ -2882,6 +2897,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
                        }
                        break;
                case LTTNG_DOMAIN_JUL:
+               case LTTNG_DOMAIN_LOG4J:
+               case LTTNG_DOMAIN_PYTHON:
                case LTTNG_DOMAIN_UST:
                        if (!cmd_ctx->session->ust_session) {
                                ret = LTTNG_ERR_NO_CHANNEL;
@@ -2963,6 +2980,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
 
                break;
        case LTTNG_DOMAIN_JUL:
+       case LTTNG_DOMAIN_LOG4J:
+       case LTTNG_DOMAIN_PYTHON:
        case LTTNG_DOMAIN_UST:
        {
                if (!ust_app_supported()) {
@@ -3056,6 +3075,8 @@ skip_domain:
                        cmd_ctx->lsm->cmd_type == LTTNG_STOP_TRACE) {
                switch (cmd_ctx->lsm->domain.type) {
                case LTTNG_DOMAIN_JUL:
+               case LTTNG_DOMAIN_LOG4J:
+               case LTTNG_DOMAIN_PYTHON:
                case LTTNG_DOMAIN_UST:
                        if (uatomic_read(&ust_consumerd_state) != CONSUMER_STARTED) {
                                ret = LTTNG_ERR_NO_USTCONSUMERD;
@@ -3116,17 +3137,11 @@ skip_domain:
        }
        case LTTNG_DISABLE_EVENT:
        {
+               /* FIXME: passing packed structure to non-packed pointer */
+               /* TODO: handle filter */
                ret = cmd_disable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type,
                                cmd_ctx->lsm->u.disable.channel_name,
-                               cmd_ctx->lsm->u.disable.name);
-               break;
-       }
-       case LTTNG_DISABLE_ALL_EVENT:
-       {
-               DBG("Disabling all events");
-
-               ret = cmd_disable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
-                               cmd_ctx->lsm->u.disable.channel_name);
+                               &cmd_ctx->lsm->u.disable.event);
                break;
        }
        case LTTNG_ENABLE_CHANNEL:
@@ -3203,12 +3218,14 @@ skip_domain:
 
                        if (bytecode_len > LTTNG_FILTER_MAX_LEN) {
                                ret = LTTNG_ERR_FILTER_INVAL;
+                               free(filter_expression);
                                free(exclusion);
                                goto error;
                        }
 
                        bytecode = zmalloc(bytecode_len);
                        if (!bytecode) {
+                               free(filter_expression);
                                free(exclusion);
                                ret = LTTNG_ERR_FILTER_NOMEM;
                                goto error;
@@ -3220,6 +3237,7 @@ skip_domain:
                        if (ret <= 0) {
                                DBG("Nothing recv() from client car len data... continuing");
                                *sock_error = 1;
+                               free(filter_expression);
                                free(bytecode);
                                free(exclusion);
                                ret = LTTNG_ERR_FILTER_INVAL;
@@ -3227,6 +3245,7 @@ skip_domain:
                        }
 
                        if ((bytecode->len + sizeof(*bytecode)) != bytecode_len) {
+                               free(filter_expression);
                                free(bytecode);
                                free(exclusion);
                                ret = LTTNG_ERR_FILTER_INVAL;
@@ -3241,16 +3260,6 @@ skip_domain:
                                kernel_poll_pipe[1]);
                break;
        }
-       case LTTNG_ENABLE_ALL_EVENT:
-       {
-               DBG("Enabling all events");
-
-               ret = cmd_enable_event_all(cmd_ctx->session, &cmd_ctx->lsm->domain,
-                               cmd_ctx->lsm->u.enable.channel_name,
-                               cmd_ctx->lsm->u.enable.event.type, NULL, NULL,
-                               kernel_poll_pipe[1]);
-               break;
-       }
        case LTTNG_LIST_TRACEPOINTS:
        {
                struct lttng_event *events;
@@ -3319,6 +3328,37 @@ skip_domain:
                ret = LTTNG_OK;
                break;
        }
+       case LTTNG_LIST_SYSCALLS:
+       {
+               struct lttng_event *events;
+               ssize_t nb_events;
+
+               nb_events = cmd_list_syscalls(&events);
+               if (nb_events < 0) {
+                       /* Return value is a negative lttng_error_code. */
+                       ret = -nb_events;
+                       goto error;
+               }
+
+               /*
+                * Setup lttng message with payload size set to the event list size in
+                * bytes and then copy list into the llm payload.
+                */
+               ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_event) * nb_events);
+               if (ret < 0) {
+                       free(events);
+                       goto setup_error;
+               }
+
+               /* Copy event list into message payload */
+               memcpy(cmd_ctx->llm->payload, events,
+                               sizeof(struct lttng_event) * nb_events);
+
+               free(events);
+
+               ret = LTTNG_OK;
+               break;
+       }
        case LTTNG_SET_CONSUMER_URI:
        {
                size_t nb_uri, len;
@@ -3439,7 +3479,7 @@ skip_domain:
        case LTTNG_LIST_DOMAINS:
        {
                ssize_t nb_dom;
-               struct lttng_domain *domains;
+               struct lttng_domain *domains = NULL;
 
                nb_dom = cmd_list_domains(cmd_ctx->session, &domains);
                if (nb_dom < 0) {
@@ -3466,7 +3506,7 @@ skip_domain:
        case LTTNG_LIST_CHANNELS:
        {
                int nb_chan;
-               struct lttng_channel *channels;
+               struct lttng_channel *channels = NULL;
 
                nb_chan = cmd_list_channels(cmd_ctx->lsm->domain.type,
                                cmd_ctx->session, &channels);
@@ -4206,9 +4246,10 @@ static void usage(void)
        fprintf(stderr, "      --verbose-consumer             Verbose mode for consumer. Activate DBG() macro.\n");
        fprintf(stderr, "      --no-kernel                    Disable kernel tracer\n");
        fprintf(stderr, "      --agent-tcp-port               Agent registration TCP port\n");
-       fprintf(stderr, "  -f  --config                       Load daemon configuration file\n");
+       fprintf(stderr, "  -f  --config PATH                  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");
+       fprintf(stderr, "      --extra-kmod-probes            Specify extra kernel module probes to load\n");
 }
 
 /*
@@ -4221,6 +4262,17 @@ static int set_option(int opt, const char *arg, const char *optname)
 {
        int ret = 0;
 
+       if (arg && arg[0] == '\0') {
+               /*
+                * This only happens if the value is read from daemon config
+                * file. This means the option requires an argument and the
+                * configuration file contains a line such as:
+                * my_option =
+                */
+               ret = -EINVAL;
+               goto end;
+       }
+
        switch (opt) {
        case 0:
                fprintf(stderr, "option %s", optname);
@@ -4395,6 +4447,14 @@ static int set_option(int opt, const char *arg, const char *optname)
                        ret = -ENOMEM;
                }
                break;
+       case 'e':
+               free(kmod_extra_probes_list);
+               kmod_extra_probes_list = strdup(arg);
+               if (!kmod_extra_probes_list) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
+               break;
        case 'f':
                /* This is handled in set_options() thus silent break. */
                break;
@@ -4404,6 +4464,22 @@ static int set_option(int opt, const char *arg, const char *optname)
                ret = -1;
        }
 
+       if (ret == -EINVAL) {
+               const char *opt_name = "unknown";
+               int i;
+
+               for (i = 0; i < sizeof(long_options) / sizeof(struct option);
+                       i++) {
+                       if (opt == long_options[i].val) {
+                               opt_name = long_options[i].name;
+                               break;
+                       }
+               }
+
+               WARN("Invalid argument provided for option \"%s\", using default value.",
+                       opt_name);
+       }
+end:
        return ret;
 }
 
@@ -5197,6 +5273,13 @@ int main(int argc, char **argv)
                /* Setup kernel tracer */
                if (!opt_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 */
This page took 0.028028 seconds and 4 git commands to generate.