#include "ust-thread.h"
#include "jul-thread.h"
#include "save.h"
+#include "load-session-thread.h"
#define CONSUMERD_FILE "lttng-consumerd"
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;
{ "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 }
};
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
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(<tng_sessiond_ready, 1) == 0) {
/*
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",
*/
if (opt_verbose_consumer) {
verbosity = "--verbose";
- } else {
+ } else if (lttng_opt_quiet) {
verbosity = "--quiet";
+ } else {
+ verbosity = "";
}
+
switch (consumer_data->type) {
case LTTNG_CONSUMER_KERNEL:
/*
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;
}
goto error;
}
- lttng_sessiond_notify_ready();
+ sessiond_notify_ready();
while (1) {
DBG("Health check ready");
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)) {
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");
}
/*
break;
case 'g':
tracing_group_name = strdup(arg);
+ if (!tracing_group_name) {
+ perror("strdup");
+ ret = -ENOMEM;
+ }
break;
case 'h':
usage();
case 'v':
/* Verbose level can increase using multiple -v */
if (arg) {
+ /* Value obtained from config file */
lttng_opt_verbose = config_parse_value(arg);
} else {
- lttng_opt_verbose += 1;
+ /* -v used on command line */
+ lttng_opt_verbose++;
}
+ /* Clamp value to [0, 3] */
+ lttng_opt_verbose = lttng_opt_verbose < 0 ? 0 :
+ (lttng_opt_verbose <= 3 ? lttng_opt_verbose : 3);
break;
case 'Z':
if (arg) {
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. */
{
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 */
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
*/
/* 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.
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;
}
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;
}
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");