Fix: Handle empty daemon configuration file lines
[lttng-tools.git] / src / bin / lttng-sessiond / main.c
index a8751c696a62c58a5b634d2671be6971369dacde..3e04f963329e6603c859164f1ee4ff4207a8e118 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <getopt.h>
 #include <grp.h>
 #include <limits.h>
 #include "health-sessiond.h"
 #include "testpoint.h"
 #include "ust-thread.h"
-#include "jul-thread.h"
+#include "agent-thread.h"
 #include "save.h"
 #include "load-session-thread.h"
+#include "syscall.h"
 
 #define CONSUMERD_FILE "lttng-consumerd"
 
@@ -153,10 +155,11 @@ static const struct option long_options[] = {
        { "verbose-consumer", 0, 0, 'Z' },
        { "no-kernel", 0, 0, 'N' },
        { "pidfile", 1, 0, 'p' },
-       { "jul-tcp-port", 1, 0, 'J' },
+       { "agent-tcp-port", 1, 0, 'J' },
        { "config", 1, 0, 'f' },
        { "load", 1, 0, 'l' },
        { "kmod-probes", 1, 0, 'P' },
+       { "extra-kmod-probes", 1, 0, 'e' },
        { NULL, 0, 0, 0 }
 };
 
@@ -204,7 +207,7 @@ static pthread_t kernel_thread;
 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 agent_reg_thread;
 static pthread_t load_session_thread;
 
 /*
@@ -289,8 +292,8 @@ long page_size;
 /* Application health monitoring */
 struct health_app *health_sessiond;
 
-/* JUL TCP port for registration. Used by the JUL thread. */
-unsigned int jul_tcp_port = DEFAULT_JUL_TCP_PORT;
+/* Agent TCP port for registration. Used by the agent thread. */
+unsigned int agent_tcp_port = DEFAULT_AGENT_TCP_PORT;
 
 /* Am I root or not. */
 int is_root;                   /* Set to 1 if the daemon is running as root */
@@ -571,7 +574,7 @@ static void cleanup(void)
        (void) unlink(path);
 
        snprintf(path, PATH_MAX, "%s/%s", rundir,
-                       DEFAULT_LTTNG_SESSIOND_JULPORT_FILE);
+                       DEFAULT_LTTNG_SESSIOND_AGENTPORT_FILE);
        DBG("Removing %s", path);
        (void) unlink(path);
 
@@ -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();
        }
@@ -1685,7 +1695,7 @@ error_create:
 static void *thread_dispatch_ust_registration(void *data)
 {
        int ret, err = -1;
-       struct cds_wfq_node *node;
+       struct cds_wfcq_node *node;
        struct ust_command *ust_cmd = NULL;
        struct ust_reg_wait_node *wait_node = NULL, *tmp_wait_node;
        struct ust_reg_wait_queue wait_queue = {
@@ -1723,7 +1733,7 @@ static void *thread_dispatch_ust_registration(void *data)
 
                        health_code_update();
                        /* Dequeue command for registration */
-                       node = cds_wfq_dequeue_blocking(&ust_cmd_queue.queue);
+                       node = cds_wfcq_dequeue_blocking(&ust_cmd_queue.head, &ust_cmd_queue.tail);
                        if (node == NULL) {
                                DBG("Woken up but nothing in the UST command queue");
                                /* Continue thread execution */
@@ -2077,11 +2087,11 @@ static void *thread_registration_apps(void *data)
                                         * Lock free enqueue the registration request. The red pill
                                         * has been taken! This apps will be part of the *system*.
                                         */
-                                       cds_wfq_enqueue(&ust_cmd_queue.queue, &ust_cmd->node);
+                                       cds_wfcq_enqueue(&ust_cmd_queue.head, &ust_cmd_queue.tail, &ust_cmd->node);
 
                                        /*
                                         * Wake the registration queue futex. Implicit memory
-                                        * barrier with the exchange in cds_wfq_enqueue.
+                                        * barrier with the exchange in cds_wfcq_enqueue.
                                         */
                                        futex_nto1_wake(&ust_cmd_queue.futex);
                                }
@@ -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()) {
@@ -3016,6 +3035,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
                        }
 
                        /* 32-bit */
+                       pthread_mutex_lock(&ustconsumer32_data.pid_mutex);
                        if (consumerd32_bin[0] != '\0' &&
                                        ustconsumer32_data.pid == 0 &&
                                        cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
@@ -3055,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;
@@ -3115,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:
@@ -3202,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;
@@ -3219,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;
@@ -3226,6 +3245,7 @@ skip_domain:
                        }
 
                        if ((bytecode->len + sizeof(*bytecode)) != bytecode_len) {
+                               free(filter_expression);
                                free(bytecode);
                                free(exclusion);
                                ret = LTTNG_ERR_FILTER_INVAL;
@@ -3240,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;
@@ -3318,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;
@@ -3438,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) {
@@ -3465,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);
@@ -4204,10 +4245,11 @@ static void usage(void)
        fprintf(stderr, "  -p, --pidfile FILE                 Write a pid to FILE name overriding the default value.\n");
        fprintf(stderr, "      --verbose-consumer             Verbose mode for consumer. Activate DBG() macro.\n");
        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, "      --agent-tcp-port               Agent registration TCP port\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");
 }
 
 /*
@@ -4220,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);
@@ -4360,22 +4413,22 @@ static int set_option(int opt, const char *arg, const char *optname)
                        ret = -ENOMEM;
                }
                break;
-       case 'J': /* JUL TCP port. */
+       case 'J': /* Agent TCP port. */
        {
                unsigned long v;
 
                errno = 0;
                v = strtoul(arg, NULL, 0);
                if (errno != 0 || !isdigit(arg[0])) {
-                       ERR("Wrong value in --jul-tcp-port parameter: %s", arg);
+                       ERR("Wrong value in --agent-tcp-port parameter: %s", arg);
                        return -1;
                }
                if (v == 0 || v >= 65535) {
-                       ERR("Port overflow in --jul-tcp-port parameter: %s", arg);
+                       ERR("Port overflow in --agent-tcp-port parameter: %s", arg);
                        return -1;
                }
-               jul_tcp_port = (uint32_t) v;
-               DBG3("JUL TCP port set to non default: %u", jul_tcp_port);
+               agent_tcp_port = (uint32_t) v;
+               DBG3("Agent TCP port set to non default: %u", agent_tcp_port);
                break;
        }
        case 'l':
@@ -4394,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;
@@ -4403,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;
 }
 
@@ -4915,9 +4992,9 @@ error:
 }
 
 /*
- * Write JUL TCP port using the rundir.
+ * Write agent TCP port using the rundir.
  */
-static void write_julport(void)
+static void write_agent_port(void)
 {
        int ret;
        char path[PATH_MAX];
@@ -4925,18 +5002,18 @@ static void write_julport(void)
        assert(rundir);
 
        ret = snprintf(path, sizeof(path), "%s/"
-                       DEFAULT_LTTNG_SESSIOND_JULPORT_FILE, rundir);
+                       DEFAULT_LTTNG_SESSIOND_AGENTPORT_FILE, rundir);
        if (ret < 0) {
-               PERROR("snprintf julport path");
+               PERROR("snprintf agent port path");
                goto error;
        }
 
        /*
-        * Create TCP JUL port file in rundir. Return value is of no importance.
+        * Create TCP agent port file in rundir. Return value is of no importance.
         * The execution will continue even though we are not able to write the
         * file.
         */
-       (void) utils_create_pid_file(jul_tcp_port, path);
+       (void) utils_create_pid_file(agent_tcp_port, path);
 
 error:
        return;
@@ -5173,8 +5250,8 @@ int main(int argc, char **argv)
         */
        ust_app_ht_alloc();
 
-       /* Initialize JUL domain subsystem. */
-       if ((ret = jul_init()) < 0) {
+       /* Initialize agent domain subsystem. */
+       if ((ret = agent_setup()) < 0) {
                /* ENOMEM at this point. */
                goto error;
        }
@@ -5196,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 */
@@ -5256,7 +5340,7 @@ int main(int argc, char **argv)
        buffer_reg_init_pid_registry();
 
        /* Init UST command queue. */
-       cds_wfq_init(&ust_cmd_queue.queue);
+       cds_wfcq_init(&ust_cmd_queue.head, &ust_cmd_queue.tail);
 
        /*
         * Get session list pointer. This pointer MUST NOT be free(). This list is
@@ -5278,7 +5362,7 @@ int main(int argc, char **argv)
        }
 
        write_pidfile();
-       write_julport();
+       write_agent_port();
 
        /* Initialize communication library */
        lttcomm_init();
@@ -5356,12 +5440,12 @@ int main(int argc, char **argv)
                goto exit_apps_notify;
        }
 
-       /* Create JUL registration thread. */
-       ret = pthread_create(&jul_reg_thread, NULL,
-                       jul_thread_manage_registration, (void *) NULL);
+       /* Create agent registration thread. */
+       ret = pthread_create(&agent_reg_thread, NULL,
+                       agent_thread_manage_registration, (void *) NULL);
        if (ret != 0) {
-               PERROR("pthread_create JUL");
-               goto exit_jul_reg;
+               PERROR("pthread_create agent");
+               goto exit_agent_reg;
        }
 
        /* Don't start this thread if kernel tracing is not requested nor root */
@@ -5387,13 +5471,13 @@ int main(int argc, char **argv)
        }
 
 exit_kernel:
-       ret = pthread_join(jul_reg_thread, &status);
+       ret = pthread_join(agent_reg_thread, &status);
        if (ret != 0) {
-               PERROR("pthread_join JUL");
+               PERROR("pthread_join agent");
                goto error;     /* join error, exit without cleanup */
        }
 
-exit_jul_reg:
+exit_agent_reg:
        ret = pthread_join(apps_notify_thread, &status);
        if (ret != 0) {
                PERROR("pthread_join apps notify");
This page took 0.032381 seconds and 4 git commands to generate.