/* Consumer daemon specific control data */
static struct consumer_data kconsumer_data = {
.type = LTTNG_CONSUMER_KERNEL,
+ .err_unix_sock_path = KCONSUMERD_ERR_SOCK_PATH,
+ .cmd_unix_sock_path = KCONSUMERD_CMD_SOCK_PATH,
};
-static struct consumer_data ustconsumer_data = {
- .type = LTTNG_CONSUMER_UST,
+static struct consumer_data ustconsumer64_data = {
+ .type = LTTNG_CONSUMER64_UST,
+ .err_unix_sock_path = USTCONSUMERD64_ERR_SOCK_PATH,
+ .cmd_unix_sock_path = USTCONSUMERD64_CMD_SOCK_PATH,
+};
+static struct consumer_data ustconsumer32_data = {
+ .type = LTTNG_CONSUMER32_UST,
+ .err_unix_sock_path = USTCONSUMERD32_ERR_SOCK_PATH,
+ .cmd_unix_sock_path = USTCONSUMERD32_CMD_SOCK_PATH,
};
static int dispatch_thread_exit;
*/
static struct ltt_session_list *session_list_ptr;
+int ust_consumerd64_fd = -1;
+int ust_consumerd32_fd = -1;
+
+static const char *consumerd64_prog = "lttng-consumerd";
+static const char *consumerd32_prog = "lttng-consumerd";
+
+static const char *consumerd64_bindir =
+ __stringify(CONFIG_64BIT_BINDIR);
+static const char *consumerd32_bindir =
+ __stringify(CONFIG_32BIT_BINDIR);
+
+static
+void setup_consumerd_path(void)
+{
+ const char *bindir;
+
+ /*
+ * Allow INSTALL_BIN_PATH to be used as a target path for the
+ * native architecture size consumer if CONFIG_NBIT_BINDIR as
+ * not been defined.
+ */
+#if (CAA_BITS_PER_LONG == 64)
+ if (!consumerd64_bindir[0]) {
+ consumerd64_bindir = INSTALL_BIN_PATH;
+ }
+#elif (CAA_BITS_PER_LONG == 32)
+ if (!consumerd32_bindir[0]) {
+ consumerd32_bindir = INSTALL_BIN_PATH;
+ }
+#else
+#error "Unknown bitness"
+#endif
+
+ /*
+ * runtime env. var. overrides the build default.
+ */
+ bindir = getenv("LTTNG_TOOLS_64BIT_BINDIR");
+ if (bindir) {
+ consumerd64_bindir = bindir;
+ }
+ bindir = getenv("LTTNG_TOOLS_32BIT_BINDIR");
+ if (bindir) {
+ consumerd32_bindir = bindir;
+ }
+}
+
/*
* Create a poll set with O_CLOEXEC and add the thread quit pipe to the set.
*/
*/
static void teardown_kernel_session(struct ltt_session *session)
{
- if (session->kernel_session != NULL) {
- DBG("Tearing down kernel session");
-
- /*
- * If a custom kernel consumer was registered, close the socket before
- * tearing down the complete kernel session structure
- */
- if (session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) {
- lttcomm_close_unix_sock(session->kernel_session->consumer_fd);
- }
+ if (!session->kernel_session)
+ return;
+ DBG("Tearing down kernel session");
- trace_kernel_destroy_session(session->kernel_session);
- /* Extra precaution */
- session->kernel_session = NULL;
+ /*
+ * If a custom kernel consumer was registered, close the socket before
+ * tearing down the complete kernel session structure
+ */
+ if (session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) {
+ lttcomm_close_unix_sock(session->kernel_session->consumer_fd);
}
+
+ trace_kernel_destroy_session(session->kernel_session);
}
/*
*/
static void teardown_ust_session(struct ltt_session *session)
{
- DBG("Tearing down UST session(s)");
+ int ret;
+ if (!session->ust_session)
+ return;
+ DBG("Tearing down UST session(s)");
+ ret = ust_app_destroy_trace_all(session->ust_session);
+ if (ret) {
+ ERR("Error in ust_app_destroy_trace_all");
+ }
trace_ust_destroy_session(session->ust_session);
}
buf_size = size;
- cmd_ctx->llm = malloc(sizeof(struct lttcomm_lttng_msg) + buf_size);
+ cmd_ctx->llm = zmalloc(sizeof(struct lttcomm_lttng_msg) + buf_size);
if (cmd_ctx->llm == NULL) {
- perror("malloc");
+ perror("zmalloc");
ret = -ENOMEM;
goto error;
}
/* Register applicaton to the session daemon */
ret = ust_app_register(&ust_cmd.reg_msg,
ust_cmd.sock);
- if (ret < 0) {
- /* Only critical ENOMEM error can be returned here */
+ if (ret == -ENOMEM) {
goto error;
+ } else if (ret < 0) {
+ break;
}
/*
}
/* Create UST registration command for enqueuing */
- ust_cmd = malloc(sizeof(struct ust_command));
+ ust_cmd = zmalloc(sizeof(struct ust_command));
if (ust_cmd == NULL) {
- perror("ust command malloc");
+ perror("ust command zmalloc");
goto error;
}
switch (consumer_data->type) {
case LTTNG_CONSUMER_KERNEL:
execl(INSTALL_BIN_PATH "/lttng-consumerd",
- "lttng-consumerd", verbosity, "-k", NULL);
+ "lttng-consumerd", verbosity, "-k",
+ "--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
+ "--consumerd-err-sock", consumer_data->err_unix_sock_path,
+ NULL);
break;
- case LTTNG_CONSUMER_UST:
- execl(INSTALL_BIN_PATH "/lttng-consumerd",
- "lttng-consumerd", verbosity, "-u", NULL);
+ case LTTNG_CONSUMER64_UST:
+ {
+ char path[PATH_MAX];
+
+ snprintf(path, PATH_MAX, "%s/%s",
+ consumerd64_bindir, consumerd64_prog);
+ execl(path, verbosity, "-u",
+ "--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
+ "--consumerd-err-sock", consumer_data->err_unix_sock_path,
+ NULL);
break;
+ }
+ case LTTNG_CONSUMER32_UST:
+ {
+ char path[PATH_MAX];
+
+ snprintf(path, PATH_MAX, "%s/%s",
+ consumerd32_bindir, consumerd32_prog);
+ execl(path, verbosity, "-u",
+ "--consumerd-cmd-sock", consumer_data->cmd_unix_sock_path,
+ "--consumerd-err-sock", consumer_data->err_unix_sock_path,
+ NULL);
+ break;
+ }
default:
perror("unknown consumer type");
exit(EXIT_FAILURE);
DBG("Creating UST session");
- session_lock_list();
- uid = session_list_ptr->count;
- session_unlock_list();
-
+ uid = session->uid;
lus = trace_ust_create_session(session->path, uid, domain);
if (lus == NULL) {
ret = LTTCOMM_UST_SESS_FAIL;
sessions[i].path[PATH_MAX - 1] = '\0';
strncpy(sessions[i].name, session->name, NAME_MAX);
sessions[i].name[NAME_MAX - 1] = '\0';
+ sessions[i].enabled = session->enabled;
i++;
}
}
channels[i].attr.read_timer_interval =
uchan->attr.read_timer_interval;
channels[i].attr.output = uchan->attr.output;
+ i++;
}
break;
}
ksession = session->kernel_session;
usess = session->ust_session;
+ if (session->enabled)
+ return LTTCOMM_UST_START_FAIL;
+ session->enabled = 1;
+
/* Kernel tracing */
if (ksession != NULL) {
struct ltt_kernel_channel *kchan;
int ret;
struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
- //struct ltt_ust_session *usess;
- //struct ltt_ust_channel *ustchan;
+ struct ltt_ust_session *usess;
/* Short cut */
ksession = session->kernel_session;
+ usess = session->ust_session;
+
+ if (!session->enabled)
+ return LTTCOMM_UST_START_FAIL;
+ session->enabled = 0;
/* Kernel tracer */
if (ksession != NULL) {
kernel_wait_quiescent(kernel_tracer_fd);
}
-#ifdef DISABLE
- /* Stop each UST session */
- DBG("Stop UST tracing");
- cds_list_for_each_entry(usess, &session->ust_session_list.head, list) {
- /* Flush all buffers before stopping */
- ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj);
- if (ret < 0) {
- ERR("UST metadata flush failed");
- }
-
- cds_list_for_each_entry(ustchan, &usess->channels.head, list) {
- ret = ustctl_flush_buffer(usess->sock, ustchan->obj);
- if (ret < 0) {
- ERR("UST flush buffer error");
- }
- }
+ /* Flag session that trace should start automatically */
+ if (usess) {
+ usess->start_trace = 0;
- ret = ustctl_stop_session(usess->sock, usess->handle);
+ ret = ust_app_stop_trace_all(usess);
if (ret < 0) {
- ret = LTTCOMM_KERN_STOP_FAIL;
+ ret = LTTCOMM_UST_START_FAIL;
goto error;
}
-
- ustctl_wait_quiescent(usess->sock);
}
-#endif
ret = LTTCOMM_OK;
/* Clean kernel session teardown */
teardown_kernel_session(session);
+ /* UST session teardown */
+ teardown_ust_session(session);
/*
* Must notify the kernel thread here to update it's poll setin order
if (session->kernel_session != NULL) {
nb_chan = session->kernel_session->channel_count;
}
- DBG3("Number of kernel channels %ld", nb_chan);
+ DBG3("Number of kernel channels %zd", nb_chan);
break;
case LTTNG_DOMAIN_UST:
if (session->ust_session != NULL) {
nb_chan = hashtable_get_count(
session->ust_session->domain_global.channels);
}
- DBG3("Number of UST global channels %ld", nb_chan);
+ DBG3("Number of UST global channels %zd", nb_chan);
break;
default:
*channels = NULL;
ret = LTTCOMM_KERN_CONSUMER_FAIL;
goto error;
}
+ } else {
+ pthread_mutex_unlock(&kconsumer_data.pid_mutex);
}
- pthread_mutex_unlock(&kconsumer_data.pid_mutex);
}
break;
case LTTNG_DOMAIN_UST:
goto error;
}
}
- /* Start the kernel consumer daemon */
- pthread_mutex_lock(&ustconsumer_data.pid_mutex);
- if (ustconsumer_data.pid == 0 &&
+ /* Start the UST consumer daemons */
+ /* 64-bit */
+ pthread_mutex_lock(&ustconsumer64_data.pid_mutex);
+ if (consumerd64_bindir[0] != '\0' &&
+ ustconsumer64_data.pid == 0 &&
cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
- pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
- ret = start_consumerd(&ustconsumer_data);
+ pthread_mutex_unlock(&ustconsumer64_data.pid_mutex);
+ ret = start_consumerd(&ustconsumer64_data);
if (ret < 0) {
- ret = LTTCOMM_KERN_CONSUMER_FAIL;
+ ret = LTTCOMM_UST_CONSUMER64_FAIL;
+ ust_consumerd64_fd = -EINVAL;
goto error;
}
- cmd_ctx->session->ust_session->consumer_fd =
- ustconsumer_data.cmd_sock;
+ ust_consumerd64_fd = ustconsumer64_data.cmd_sock;
+ } else {
+ pthread_mutex_unlock(&ustconsumer64_data.pid_mutex);
+ }
+ /* 32-bit */
+ if (consumerd32_bindir[0] != '\0' &&
+ ustconsumer32_data.pid == 0 &&
+ cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
+ pthread_mutex_unlock(&ustconsumer32_data.pid_mutex);
+ ret = start_consumerd(&ustconsumer32_data);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CONSUMER32_FAIL;
+ ust_consumerd32_fd = -EINVAL;
+ goto error;
+ }
+ ust_consumerd32_fd = ustconsumer32_data.cmd_sock;
+ } else {
+ pthread_mutex_unlock(&ustconsumer32_data.pid_mutex);
}
- pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
}
break;
}
}
/* Allocate context command to process the client request */
- cmd_ctx = malloc(sizeof(struct command_ctx));
+ cmd_ctx = zmalloc(sizeof(struct command_ctx));
if (cmd_ctx == NULL) {
- perror("malloc cmd_ctx");
+ perror("zmalloc cmd_ctx");
goto error;
}
/* Allocate data buffer for reception */
- cmd_ctx->lsm = malloc(sizeof(struct lttcomm_session_msg));
+ cmd_ctx->lsm = zmalloc(sizeof(struct lttcomm_session_msg));
if (cmd_ctx->lsm == NULL) {
- perror("malloc cmd_ctx->lsm");
+ perror("zmalloc cmd_ctx->lsm");
goto error;
}
if (ret < 0) {
/*
* TODO: Inform client somehow of the fatal error. At
- * this point, ret < 0 means that a malloc failed
+ * this point, ret < 0 means that a zmalloc failed
* (ENOMEM). Error detected but still accept command.
*/
clean_command_ctx(&cmd_ctx);
fprintf(stderr, " -a, --apps-sock PATH Specify path for apps unix socket\n");
fprintf(stderr, " --kconsumerd-err-sock PATH Specify path for the kernel consumer error socket\n");
fprintf(stderr, " --kconsumerd-cmd-sock PATH Specify path for the kernel consumer command socket\n");
- fprintf(stderr, " --ustconsumerd-err-sock PATH Specify path for the UST consumer error socket\n");
- fprintf(stderr, " --ustconsumerd-cmd-sock PATH Specify path for the UST consumer command socket\n");
+ fprintf(stderr, " --ustconsumerd32-err-sock PATH Specify path for the 32-bit UST consumer error socket\n");
+ fprintf(stderr, " --ustconsumerd64-err-sock PATH Specify path for the 64-bit UST consumer error socket\n");
+ fprintf(stderr, " --ustconsumerd32-cmd-sock PATH Specify path for the 32-bit UST consumer command socket\n");
+ fprintf(stderr, " --ustconsumerd64-cmd-sock PATH Specify path for the 64-bit UST consumer command socket\n");
+ fprintf(stderr, " --ustconsumerd32 PATH Specify path for the 32-bit UST consumer daemon binary\n");
+ fprintf(stderr, " --ustconsumerd64 PATH Specify path for the 64-bit UST consumer daemon binary\n");
fprintf(stderr, " -d, --daemonize Start as a daemon.\n");
fprintf(stderr, " -g, --group NAME Specify the tracing group name. (default: tracing)\n");
fprintf(stderr, " -V, --version Show version number.\n");
{ "apps-sock", 1, 0, 'a' },
{ "kconsumerd-cmd-sock", 1, 0, 'C' },
{ "kconsumerd-err-sock", 1, 0, 'E' },
- { "ustconsumerd-cmd-sock", 1, 0, 'D' },
- { "ustconsumerd-err-sock", 1, 0, 'F' },
+ { "ustconsumerd64", 1, 0, 't' },
+ { "ustconsumerd64-cmd-sock", 1, 0, 'D' },
+ { "ustconsumerd64-err-sock", 1, 0, 'F' },
+ { "ustconsumerd32", 1, 0, 'u' },
+ { "ustconsumerd32-cmd-sock", 1, 0, 'G' },
+ { "ustconsumerd32-err-sock", 1, 0, 'H' },
{ "daemonize", 0, 0, 'd' },
{ "sig-parent", 0, 0, 'S' },
{ "help", 0, 0, 'h' },
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:C:E:D:F:Z",
+ c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:C:E:D:F:Z:u:t",
long_options, &option_index);
if (c == -1) {
break;
opt_daemon = 1;
break;
case 'g':
- opt_tracing_group = strdup(optarg);
+ opt_tracing_group = optarg;
break;
case 'h':
usage();
snprintf(kconsumer_data.cmd_unix_sock_path, PATH_MAX, "%s", optarg);
break;
case 'F':
- snprintf(ustconsumer_data.err_unix_sock_path, PATH_MAX, "%s", optarg);
+ snprintf(ustconsumer64_data.err_unix_sock_path, PATH_MAX, "%s", optarg);
break;
case 'D':
- snprintf(ustconsumer_data.cmd_unix_sock_path, PATH_MAX, "%s", optarg);
+ snprintf(ustconsumer64_data.cmd_unix_sock_path, PATH_MAX, "%s", optarg);
+ break;
+ case 'H':
+ snprintf(ustconsumer32_data.err_unix_sock_path, PATH_MAX, "%s", optarg);
+ break;
+ case 'G':
+ snprintf(ustconsumer32_data.cmd_unix_sock_path, PATH_MAX, "%s", optarg);
break;
case 'q':
opt_quiet = 1;
case 'Z':
opt_verbose_consumer += 1;
break;
+ case 'u':
+ consumerd32_bindir = optarg;
+ break;
+ case 't':
+ consumerd64_bindir = optarg;
+ break;
default:
/* Unknown option or other error.
* Error is printed by getopt, just return */
perror("chown");
}
- /* ustconsumer error socket path */
- ret = chown(ustconsumer_data.err_unix_sock_path, 0, gid);
+ /* 64-bit ustconsumer error socket path */
+ ret = chown(ustconsumer64_data.err_unix_sock_path, 0, gid);
if (ret < 0) {
- ERR("Unable to set group on %s", ustconsumer_data.err_unix_sock_path);
+ ERR("Unable to set group on %s", ustconsumer64_data.err_unix_sock_path);
+ perror("chown");
+ }
+
+ /* 32-bit ustconsumer compat32 error socket path */
+ ret = chown(ustconsumer32_data.err_unix_sock_path, 0, gid);
+ if (ret < 0) {
+ ERR("Unable to set group on %s", ustconsumer32_data.err_unix_sock_path);
perror("chown");
}
static int set_consumer_sockets(struct consumer_data *consumer_data)
{
int ret;
- const char *path = consumer_data->type == LTTNG_CONSUMER_KERNEL ?
- KCONSUMERD_PATH : USTCONSUMERD_PATH;
-
- if (strlen(consumer_data->err_unix_sock_path) == 0) {
- snprintf(consumer_data->err_unix_sock_path, PATH_MAX,
- consumer_data->type == LTTNG_CONSUMER_KERNEL ?
- KCONSUMERD_ERR_SOCK_PATH :
- USTCONSUMERD_ERR_SOCK_PATH);
- }
+ const char *path;
- if (strlen(consumer_data->cmd_unix_sock_path) == 0) {
- snprintf(consumer_data->cmd_unix_sock_path, PATH_MAX,
- consumer_data->type == LTTNG_CONSUMER_KERNEL ?
- KCONSUMERD_CMD_SOCK_PATH :
- USTCONSUMERD_CMD_SOCK_PATH);
+ switch (consumer_data->type) {
+ case LTTNG_CONSUMER_KERNEL:
+ path = KCONSUMERD_PATH;
+ break;
+ case LTTNG_CONSUMER64_UST:
+ path = USTCONSUMERD64_PATH;
+ break;
+ case LTTNG_CONSUMER32_UST:
+ path = USTCONSUMERD32_PATH;
+ break;
+ default:
+ ERR("Consumer type unknown");
+ ret = -EINVAL;
+ goto error;
}
ret = mkdir(path, S_IRWXU | S_IRWXG);
goto error;
}
+ setup_consumerd_path();
+
/* Parse arguments */
progname = argv[0];
if ((ret = parse_args(argc, argv) < 0)) {
goto exit;
}
- ret = set_consumer_sockets(&ustconsumer_data);
+ ret = set_consumer_sockets(&ustconsumer64_data);
if (ret < 0) {
goto exit;
}
+
+ ret = set_consumer_sockets(&ustconsumer32_data);
+ if (ret < 0) {
+ goto exit;
+ }
+
/* Setup kernel tracer */
init_kernel_tracer();