#include <sys/wait.h>
#include <urcu/futex.h>
#include <unistd.h>
+#include <config.h>
-#include <ltt-kconsumerd.h>
+#include <lttng-consumerd.h>
#include <lttng-sessiond-comm.h>
-#include <lttng/lttng-kconsumerd.h>
+#include <lttng/lttng-consumer.h>
+
#include <lttngerr.h>
#include "channel.h"
#include "context.h"
#include "event.h"
#include "futex.h"
+#include "hashtable.h"
#include "kernel-ctl.h"
#include "ltt-sessiond.h"
#include "shm.h"
-#include "traceable-app.h"
+#include "ust-app.h"
#include "ust-ctl.h"
#include "utils.h"
-#include "ust-ctl.h"
+
+struct consumer_data {
+ enum lttng_consumer_type type;
+
+ pthread_t thread; /* Worker thread interacting with the consumer */
+ sem_t sem;
+
+ /* Mutex to control consumerd pid assignation */
+ pthread_mutex_t pid_mutex;
+ pid_t pid;
+
+ int err_sock;
+ int cmd_sock;
+
+ /* consumer error and command Unix socket path */
+ char err_unix_sock_path[PATH_MAX];
+ char cmd_unix_sock_path[PATH_MAX];
+};
/* Const values */
const char default_home_dir[] = DEFAULT_HOME_DIR;
/* Variables */
int opt_verbose; /* Not static for lttngerr.h */
-int opt_verbose_kconsumerd; /* Not static for lttngerr.h */
+int opt_verbose_consumer; /* Not static for lttngerr.h */
int opt_quiet; /* Not static for lttngerr.h */
const char *progname;
static int opt_daemon;
static int is_root; /* Set to 1 if the daemon is running as root */
static pid_t ppid; /* Parent PID for --sig-parent option */
-static pid_t kconsumerd_pid;
+
+/* Consumer daemon specific control data */
+static struct consumer_data kconsumer_data = {
+ .type = LTTNG_CONSUMER_KERNEL,
+};
+static struct consumer_data ustconsumer_data = {
+ .type = LTTNG_CONSUMER_UST,
+};
+
static int dispatch_thread_exit;
/* Global application Unix socket path */
static char apps_unix_sock_path[PATH_MAX];
/* Global client Unix socket path */
static char client_unix_sock_path[PATH_MAX];
-/* kconsumerd error and command Unix socket path */
-static char kconsumerd_err_unix_sock_path[PATH_MAX];
-static char kconsumerd_cmd_unix_sock_path[PATH_MAX];
/* global wait shm path for UST */
static char wait_shm_path[PATH_MAX];
/* Sockets and FDs */
static int client_sock;
static int apps_sock;
-static int kconsumerd_err_sock;
-static int kconsumerd_cmd_sock;
static int kernel_tracer_fd;
static int kernel_poll_pipe[2];
static int apps_cmd_pipe[2];
/* Pthread, Mutexes and Semaphores */
-static pthread_t kconsumerd_thread;
static pthread_t apps_thread;
static pthread_t reg_apps_thread;
static pthread_t client_thread;
static pthread_t kernel_thread;
static pthread_t dispatch_thread;
-static sem_t kconsumerd_sem;
-
-/* Mutex to control kconsumerd pid assignation */
-static pthread_mutex_t kconsumerd_pid_mutex;
/*
* UST registration command queue. This queue is tied with a futex and uses a N
* If a custom kernel consumer was registered, close the socket before
* tearing down the complete kernel session structure
*/
- if (session->kernel_session->consumer_fd != kconsumerd_cmd_sock) {
+ if (session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) {
lttcomm_close_unix_sock(session->kernel_session->consumer_fd);
}
}
}
+/*
+ * Complete teardown of all UST sessions. This will free everything on his path
+ * and destroy the core essence of all ust sessions :)
+ */
+static void teardown_ust_session(struct ltt_session *session)
+{
+ DBG("Tearing down UST session(s)");
+
+ trace_ust_destroy_session(session->ust_session);
+}
+
/*
* Stop all threads by closing the thread quit pipe.
*/
cds_list_for_each_entry_safe(sess, stmp,
&session_list_ptr->head, list) {
teardown_kernel_session(sess);
- // TODO complete session cleanup (including UST)
+ teardown_ust_session(sess);
+ free(sess);
}
}
DBG("Closing all UST sockets");
- clean_traceable_apps_list();
+ ust_app_clean_list();
- pthread_mutex_destroy(&kconsumerd_pid_mutex);
+ pthread_mutex_destroy(&kconsumer_data.pid_mutex);
DBG("Closing kernel fd");
close(kernel_tracer_fd);
/*
* Send all stream fds of kernel channel to the consumer.
*/
-static int send_kconsumerd_channel_fds(int sock,
- struct ltt_kernel_channel *channel)
+static int send_kconsumer_channel_streams(struct consumer_data *consumer_data,
+ int sock, struct ltt_kernel_channel *channel)
{
int ret;
- size_t nb_fd;
struct ltt_kernel_stream *stream;
- struct lttcomm_kconsumerd_header lkh;
- struct lttcomm_kconsumerd_msg lkm;
+ struct lttcomm_consumer_msg lkm;
- DBG("Sending fds of channel %s to kernel consumer",
+ DBG("Sending streams of channel %s to kernel consumer",
channel->channel->name);
- nb_fd = channel->stream_count;
-
- /* Setup header */
- lkh.payload_size = nb_fd * sizeof(struct lttcomm_kconsumerd_msg);
- lkh.cmd_type = ADD_STREAM;
-
- DBG("Sending kconsumerd header");
-
- ret = lttcomm_send_unix_sock(sock, &lkh,
- sizeof(struct lttcomm_kconsumerd_header));
+ /* Send channel */
+ lkm.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
+ lkm.u.channel.channel_key = channel->fd;
+ lkm.u.channel.max_sb_size = channel->channel->attr.subbuf_size;
+ lkm.u.channel.mmap_len = 0; /* for kernel */
+ DBG("Sending channel %d to consumer", lkm.u.channel.channel_key);
+ ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
if (ret < 0) {
- perror("send kconsumerd header");
+ perror("send consumer channel");
goto error;
}
+ /* Send streams */
cds_list_for_each_entry(stream, &channel->stream_list.head, list) {
- if (stream->fd != 0) {
- lkm.fd = stream->fd;
- lkm.state = stream->state;
- lkm.max_sb_size = channel->channel->attr.subbuf_size;
- lkm.output = channel->channel->attr.output;
- strncpy(lkm.path_name, stream->pathname, PATH_MAX);
- lkm.path_name[PATH_MAX - 1] = '\0';
-
- DBG("Sending fd %d to kconsumerd", lkm.fd);
-
- ret = lttcomm_send_fds_unix_sock(sock, &lkm,
- &lkm.fd, 1, sizeof(lkm));
- if (ret < 0) {
- perror("send kconsumerd fd");
- goto error;
- }
+ if (!stream->fd) {
+ continue;
+ }
+ lkm.cmd_type = LTTNG_CONSUMER_ADD_STREAM;
+ lkm.u.stream.channel_key = channel->fd;
+ lkm.u.stream.stream_key = stream->fd;
+ lkm.u.stream.state = stream->state;
+ lkm.u.stream.output = channel->channel->attr.output;
+ lkm.u.stream.mmap_len = 0; /* for kernel */
+ strncpy(lkm.u.stream.path_name, stream->pathname, PATH_MAX - 1);
+ lkm.u.stream.path_name[PATH_MAX - 1] = '\0';
+ DBG("Sending stream %d to consumer", lkm.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
+ if (ret < 0) {
+ perror("send consumer stream");
+ goto error;
+ }
+ ret = lttcomm_send_fds_unix_sock(sock, &stream->fd, 1);
+ if (ret < 0) {
+ perror("send consumer stream ancillary data");
+ goto error;
}
}
- DBG("Kconsumerd channel fds sent");
+ DBG("consumer channel streams sent");
return 0;
/*
* Send all stream fds of the kernel session to the consumer.
*/
-static int send_kconsumerd_fds(struct ltt_kernel_session *session)
+static int send_kconsumer_session_streams(struct consumer_data *consumer_data,
+ struct ltt_kernel_session *session)
{
int ret;
struct ltt_kernel_channel *chan;
- struct lttcomm_kconsumerd_header lkh;
- struct lttcomm_kconsumerd_msg lkm;
-
- /* Setup header */
- lkh.payload_size = sizeof(struct lttcomm_kconsumerd_msg);
- lkh.cmd_type = ADD_STREAM;
-
- DBG("Sending kconsumerd header for metadata");
-
- ret = lttcomm_send_unix_sock(session->consumer_fd, &lkh,
- sizeof(struct lttcomm_kconsumerd_header));
- if (ret < 0) {
- perror("send kconsumerd header");
- goto error;
- }
+ struct lttcomm_consumer_msg lkm;
+ int sock = session->consumer_fd;
DBG("Sending metadata stream fd");
- /* Extra protection. It's NOT suppose to be set to 0 at this point */
+ /* Extra protection. It's NOT supposed to be set to 0 at this point */
if (session->consumer_fd == 0) {
- session->consumer_fd = kconsumerd_cmd_sock;
+ session->consumer_fd = consumer_data->cmd_sock;
}
if (session->metadata_stream_fd != 0) {
- /* Send metadata stream fd first */
- lkm.fd = session->metadata_stream_fd;
- lkm.state = ACTIVE_FD;
- lkm.max_sb_size = session->metadata->conf->attr.subbuf_size;
- lkm.output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
- strncpy(lkm.path_name, session->metadata->pathname, PATH_MAX);
- lkm.path_name[PATH_MAX - 1] = '\0';
-
- ret = lttcomm_send_fds_unix_sock(session->consumer_fd, &lkm,
- &lkm.fd, 1, sizeof(lkm));
+ /* Send metadata channel fd */
+ lkm.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
+ lkm.u.channel.channel_key = session->metadata->fd;
+ lkm.u.channel.max_sb_size = session->metadata->conf->attr.subbuf_size;
+ lkm.u.channel.mmap_len = 0; /* for kernel */
+ DBG("Sending metadata channel %d to consumer", lkm.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
+ if (ret < 0) {
+ perror("send consumer channel");
+ goto error;
+ }
+
+ /* Send metadata stream fd */
+ lkm.cmd_type = LTTNG_CONSUMER_ADD_STREAM;
+ lkm.u.stream.channel_key = session->metadata->fd;
+ lkm.u.stream.stream_key = session->metadata_stream_fd;
+ lkm.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
+ lkm.u.stream.output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
+ lkm.u.stream.mmap_len = 0; /* for kernel */
+ strncpy(lkm.u.stream.path_name, session->metadata->pathname, PATH_MAX - 1);
+ lkm.u.stream.path_name[PATH_MAX - 1] = '\0';
+ DBG("Sending metadata stream %d to consumer", lkm.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
+ if (ret < 0) {
+ perror("send consumer stream");
+ goto error;
+ }
+ ret = lttcomm_send_fds_unix_sock(sock, &session->metadata_stream_fd, 1);
if (ret < 0) {
- perror("send kconsumerd fd");
+ perror("send consumer stream");
goto error;
}
}
cds_list_for_each_entry(chan, &session->channel_list.head, list) {
- ret = send_kconsumerd_channel_fds(session->consumer_fd, chan);
+ ret = send_kconsumer_channel_streams(consumer_data, sock, chan);
if (ret < 0) {
goto error;
}
}
- DBG("Kconsumerd fds (metadata and channel streams) sent");
+ DBG("consumer fds (metadata and channel streams) sent");
return 0;
*
* Useful for CPU hotplug feature.
*/
-static int update_kernel_stream(int fd)
+static int update_kernel_stream(struct consumer_data *consumer_data, int fd)
{
int ret = 0;
struct ltt_session *session;
/* This is not suppose to be 0 but this is an extra security check */
if (session->kernel_session->consumer_fd == 0) {
- session->kernel_session->consumer_fd = kconsumerd_cmd_sock;
+ session->kernel_session->consumer_fd = consumer_data->cmd_sock;
}
cds_list_for_each_entry(channel,
* that tracing is started so it is safe to send our updated
* stream fds.
*/
- if (session->kernel_session->kconsumer_fds_sent == 1) {
- ret = send_kconsumerd_channel_fds(
+ if (session->kernel_session->consumer_fds_sent == 1) {
+ ret = send_kconsumer_channel_streams(consumer_data,
session->kernel_session->consumer_fd, channel);
if (ret < 0) {
goto error;
while (1) {
if (update_poll_flag == 1) {
+ /*
+ * Reset number of fd in the poll set. Always 2 since there is the thread
+ * quit pipe and the kernel pipe.
+ */
+ events.nb_fd = 2;
+
ret = update_kernel_poll(&events);
if (ret < 0) {
goto error;
* kernel session and updating the kernel consumer
*/
if (revents & LPOLLIN) {
- ret = update_kernel_stream(pollfd);
+ ret = update_kernel_stream(&kconsumer_data, pollfd);
if (ret < 0) {
continue;
}
}
/*
- * This thread manage the kconsumerd error sent back to the session daemon.
+ * This thread manage the consumer error sent back to the session daemon.
*/
-static void *thread_manage_kconsumerd(void *data)
+static void *thread_manage_consumer(void *data)
{
int sock = 0, i, ret, pollfd;
uint32_t revents, nb_fd;
enum lttcomm_return_code code;
struct lttng_poll_event events;
+ struct consumer_data *consumer_data = data;
- DBG("[thread] Manage kconsumerd started");
+ DBG("[thread] Manage consumer started");
- ret = lttcomm_listen_unix_sock(kconsumerd_err_sock);
+ ret = lttcomm_listen_unix_sock(consumer_data->err_sock);
if (ret < 0) {
goto error;
}
goto error;
}
- ret = lttng_poll_add(&events, kconsumerd_err_sock, LPOLLIN | LPOLLRDHUP);
+ ret = lttng_poll_add(&events, consumer_data->err_sock, LPOLLIN | LPOLLRDHUP);
if (ret < 0) {
goto error;
}
}
/* Event on the registration socket */
- if (pollfd == kconsumerd_err_sock) {
+ if (pollfd == consumer_data->err_sock) {
if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
- ERR("Kconsumerd err socket poll error");
+ ERR("consumer err socket poll error");
goto error;
}
}
}
- sock = lttcomm_accept_unix_sock(kconsumerd_err_sock);
+ sock = lttcomm_accept_unix_sock(consumer_data->err_sock);
if (sock < 0) {
goto error;
}
+ DBG2("Receiving code from consumer err_sock");
+
/* Getting status code from kconsumerd */
ret = lttcomm_recv_unix_sock(sock, &code,
sizeof(enum lttcomm_return_code));
goto error;
}
- if (code == KCONSUMERD_COMMAND_SOCK_READY) {
- kconsumerd_cmd_sock =
- lttcomm_connect_unix_sock(kconsumerd_cmd_unix_sock_path);
- if (kconsumerd_cmd_sock < 0) {
- sem_post(&kconsumerd_sem);
- perror("kconsumerd connect");
+ if (code == CONSUMERD_COMMAND_SOCK_READY) {
+ consumer_data->cmd_sock =
+ lttcomm_connect_unix_sock(consumer_data->cmd_unix_sock_path);
+ if (consumer_data->cmd_sock < 0) {
+ sem_post(&consumer_data->sem);
+ PERROR("consumer connect");
goto error;
}
/* Signal condition to tell that the kconsumerd is ready */
- sem_post(&kconsumerd_sem);
- DBG("Kconsumerd command socket ready");
+ sem_post(&consumer_data->sem);
+ DBG("consumer command socket ready");
} else {
- DBG("Kconsumerd error when waiting for SOCK_READY : %s",
+ ERR("consumer error when waiting for SOCK_READY : %s",
lttcomm_get_readable_code(-code));
goto error;
}
/* Remove the kconsumerd error sock since we've established a connexion */
- ret = lttng_poll_del(&events, kconsumerd_err_sock);
+ ret = lttng_poll_del(&events, consumer_data->err_sock);
if (ret < 0) {
goto error;
}
/* Event on the kconsumerd socket */
if (pollfd == sock) {
if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
- ERR("Kconsumerd err socket second poll error");
+ ERR("consumer err socket second poll error");
goto error;
}
}
ret = lttcomm_recv_unix_sock(sock, &code,
sizeof(enum lttcomm_return_code));
if (ret <= 0) {
- ERR("Kconsumerd closed the command socket");
+ ERR("consumer closed the command socket");
goto error;
}
- ERR("Kconsumerd return code : %s", lttcomm_get_readable_code(-code));
+ ERR("consumer return code : %s", lttcomm_get_readable_code(-code));
error:
- DBG("Kconsumerd thread dying");
- close(kconsumerd_err_sock);
- close(kconsumerd_cmd_sock);
+ DBG("consumer thread dying");
+ close(consumer_data->err_sock);
+ close(consumer_data->cmd_sock);
close(sock);
- unlink(kconsumerd_err_unix_sock_path);
- unlink(kconsumerd_cmd_unix_sock_path);
- kconsumerd_pid = 0;
+ unlink(consumer_data->err_unix_sock_path);
+ unlink(consumer_data->cmd_unix_sock_path);
+ consumer_data->pid = 0;
lttng_poll_clean(&events);
DBG("[thread] Manage application started");
+ rcu_register_thread();
+ rcu_thread_online();
+
ret = create_thread_poll_set(&events, 2);
if (ret < 0) {
goto error;
}
/* Register applicaton to the session daemon */
- ret = register_traceable_app(&ust_cmd.reg_msg,
+ ret = ust_app_register(&ust_cmd.reg_msg,
ust_cmd.sock);
if (ret < 0) {
/* Only critical ENOMEM error can be returned here */
* If the registration is not possible, we simply
* unregister the apps and continue
*/
- unregister_traceable_app(ust_cmd.sock);
+ ust_app_unregister(ust_cmd.sock);
} else {
/*
* We just need here to monitor the close of the UST
}
/* Socket closed */
- unregister_traceable_app(pollfd);
+ ust_app_unregister(pollfd);
break;
}
}
lttng_poll_clean(&events);
+ rcu_thread_offline();
+ rcu_unregister_thread();
return NULL;
}
/* Dequeue command for registration */
node = cds_wfq_dequeue_blocking(&ust_cmd_queue.queue);
if (node == NULL) {
- DBG("Waked up but nothing in the UST command queue");
+ DBG("Woken up but nothing in the UST command queue");
/* Continue thread execution */
break;
}
}
/*
- * Start the thread_manage_kconsumerd. This must be done after a kconsumerd
+ * Start the thread_manage_consumer. This must be done after a lttng-consumerd
* exec or it will fails.
*/
-static int spawn_kconsumerd_thread(void)
+static int spawn_consumer_thread(struct consumer_data *consumer_data)
{
int ret;
+ struct timespec timeout;
+
+ timeout.tv_sec = DEFAULT_SEM_WAIT_TIMEOUT;
+ timeout.tv_nsec = 0;
/* Setup semaphore */
- sem_init(&kconsumerd_sem, 0, 0);
+ ret = sem_init(&consumer_data->sem, 0, 0);
+ if (ret < 0) {
+ PERROR("sem_init consumer semaphore");
+ goto error;
+ }
- ret = pthread_create(&kconsumerd_thread, NULL,
- thread_manage_kconsumerd, (void *) NULL);
+ ret = pthread_create(&consumer_data->thread, NULL,
+ thread_manage_consumer, consumer_data);
if (ret != 0) {
- perror("pthread_create kconsumerd");
+ PERROR("pthread_create consumer");
+ ret = -1;
goto error;
}
- /* Wait for the kconsumerd thread to be ready */
- sem_wait(&kconsumerd_sem);
+ /* Get time for sem_timedwait absolute timeout */
+ ret = clock_gettime(CLOCK_REALTIME, &timeout);
+ if (ret < 0) {
+ PERROR("clock_gettime spawn consumer");
+ /* Infinite wait for the kconsumerd thread to be ready */
+ ret = sem_wait(&consumer_data->sem);
+ } else {
+ /* Normal timeout if the gettime was successful */
+ timeout.tv_sec += DEFAULT_SEM_WAIT_TIMEOUT;
+ ret = sem_timedwait(&consumer_data->sem, &timeout);
+ }
- if (kconsumerd_pid == 0) {
+ if (ret < 0) {
+ if (errno == ETIMEDOUT) {
+ /*
+ * Call has timed out so we kill the kconsumerd_thread and return
+ * an error.
+ */
+ ERR("The consumer thread was never ready. Killing it");
+ ret = pthread_cancel(consumer_data->thread);
+ if (ret < 0) {
+ PERROR("pthread_cancel consumer thread");
+ }
+ } else {
+ PERROR("semaphore wait failed consumer thread");
+ }
+ goto error;
+ }
+
+ pthread_mutex_lock(&consumer_data->pid_mutex);
+ if (consumer_data->pid == 0) {
ERR("Kconsumerd did not start");
+ pthread_mutex_unlock(&consumer_data->pid_mutex);
goto error;
}
+ pthread_mutex_unlock(&consumer_data->pid_mutex);
return 0;
error:
- ret = LTTCOMM_KERN_CONSUMER_FAIL;
return ret;
}
/*
- * Join kernel consumer thread
+ * Join consumer thread
*/
-static int join_kconsumerd_thread(void)
+static int join_consumer_thread(struct consumer_data *consumer_data)
{
void *status;
int ret;
- if (kconsumerd_pid != 0) {
- ret = kill(kconsumerd_pid, SIGTERM);
+ if (consumer_data->pid != 0) {
+ ret = kill(consumer_data->pid, SIGTERM);
if (ret) {
- ERR("Error killing kconsumerd");
+ ERR("Error killing consumer daemon");
return ret;
}
- return pthread_join(kconsumerd_thread, &status);
+ return pthread_join(consumer_data->thread, &status);
} else {
return 0;
}
}
/*
- * Fork and exec a kernel consumer daemon (kconsumerd).
+ * Fork and exec a consumer daemon (consumerd).
*
* Return pid if successful else -1.
*/
-static pid_t spawn_kconsumerd(void)
+static pid_t spawn_consumerd(struct consumer_data *consumer_data)
{
int ret;
pid_t pid;
const char *verbosity;
- DBG("Spawning kconsumerd");
+ DBG("Spawning consumerd");
pid = fork();
if (pid == 0) {
/*
- * Exec kconsumerd.
+ * Exec consumerd.
*/
- if (opt_verbose > 1 || opt_verbose_kconsumerd) {
+ if (opt_verbose > 1 || opt_verbose_consumer) {
verbosity = "--verbose";
} else {
verbosity = "--quiet";
}
- execl(INSTALL_BIN_PATH "/ltt-kconsumerd",
- "ltt-kconsumerd", verbosity, NULL);
+ switch (consumer_data->type) {
+ case LTTNG_CONSUMER_KERNEL:
+ execl(INSTALL_BIN_PATH "/lttng-consumerd",
+ "lttng-consumerd", verbosity, "-k", NULL);
+ break;
+ case LTTNG_CONSUMER_UST:
+ execl(INSTALL_BIN_PATH "/lttng-consumerd",
+ "lttng-consumerd", verbosity, "-u", NULL);
+ break;
+ default:
+ perror("unknown consumer type");
+ exit(EXIT_FAILURE);
+ }
if (errno != 0) {
perror("kernel start consumer exec");
}
exit(EXIT_FAILURE);
} else if (pid > 0) {
ret = pid;
- goto error;
} else {
- perror("kernel start consumer fork");
+ perror("start consumer fork");
ret = -errno;
- goto error;
}
-
-error:
return ret;
}
/*
- * Spawn the kconsumerd daemon and session daemon thread.
+ * Spawn the consumerd daemon and session daemon thread.
*/
-static int start_kconsumerd(void)
+static int start_consumerd(struct consumer_data *consumer_data)
{
int ret;
- pthread_mutex_lock(&kconsumerd_pid_mutex);
- if (kconsumerd_pid != 0) {
- pthread_mutex_unlock(&kconsumerd_pid_mutex);
+ pthread_mutex_lock(&consumer_data->pid_mutex);
+ if (consumer_data->pid != 0) {
+ pthread_mutex_unlock(&consumer_data->pid_mutex);
goto end;
}
- ret = spawn_kconsumerd();
+ ret = spawn_consumerd(consumer_data);
if (ret < 0) {
- ERR("Spawning kconsumerd failed");
- ret = LTTCOMM_KERN_CONSUMER_FAIL;
- pthread_mutex_unlock(&kconsumerd_pid_mutex);
+ ERR("Spawning consumerd failed");
+ pthread_mutex_unlock(&consumer_data->pid_mutex);
goto error;
}
- /* Setting up the global kconsumerd_pid */
- kconsumerd_pid = ret;
- pthread_mutex_unlock(&kconsumerd_pid_mutex);
+ /* Setting up the consumer_data pid */
+ consumer_data->pid = ret;
+ DBG2("Consumer pid %d", consumer_data->pid);
+ pthread_mutex_unlock(&consumer_data->pid_mutex);
- DBG("Kconsumerd pid %d", ret);
-
- DBG("Spawning kconsumerd thread");
- ret = spawn_kconsumerd_thread();
+ DBG2("Spawning consumer control thread");
+ ret = spawn_consumer_thread(consumer_data);
if (ret < 0) {
- ERR("Fatal error spawning kconsumerd thread");
+ ERR("Fatal error spawning consumer control thread");
goto error;
}
ret = mkdir_recursive(path, S_IRWXU | S_IRWXG, geteuid(), getegid());
if (ret < 0) {
+ PERROR("Cannot create debugfs path");
goto error;
}
ret = mount(type, path, type, 0, NULL);
if (ret < 0) {
- perror("mount debugfs");
+ PERROR("Cannot mount debugfs");
goto error;
}
int ret;
char *proc_mounts = "/proc/mounts";
char line[256];
- char *debugfs_path = NULL, *lttng_path;
+ char *debugfs_path = NULL, *lttng_path = NULL;
FILE *fp;
/* Detect debugfs */
}
ret = mount_debugfs(debugfs_path);
if (ret < 0) {
+ perror("Cannot mount debugfs");
goto error;
}
}
{
int ret = 0;
- if (session->kconsumer_fds_sent == 0) {
+ if (session->consumer_fds_sent == 0) {
/*
* Assign default kernel consumer socket if no consumer assigned to the
* kernel session. At this point, it's NOT suppose to be 0 but this is
* an extra security check.
*/
if (session->consumer_fd == 0) {
- session->consumer_fd = kconsumerd_cmd_sock;
+ session->consumer_fd = kconsumer_data.cmd_sock;
}
- ret = send_kconsumerd_fds(session);
+ ret = send_kconsumer_session_streams(&kconsumer_data, session);
if (ret < 0) {
ret = LTTCOMM_KERN_CONSUMER_FAIL;
goto error;
}
- session->kconsumer_fds_sent = 1;
+ session->consumer_fds_sent = 1;
}
error:
/*
* Create an UST session and add it to the session ust list.
*/
-static int create_ust_session(pid_t pid, struct ltt_session *session)
+static int create_ust_session(struct ltt_session *session,
+ struct lttng_domain *domain)
{
- int ret = -1;
- struct ltt_ust_session *lus;
+ int ret;
+ unsigned int uid;
+ struct ltt_ust_session *lus = NULL;
+
+ switch (domain->type) {
+ case LTTNG_DOMAIN_UST:
+ break;
+ default:
+ ret = LTTCOMM_UNKNOWN_DOMAIN;
+ goto error;
+ }
DBG("Creating UST session");
- lus = trace_ust_create_session(session->path, pid);
+ session_lock_list();
+ uid = session_list_ptr->count;
+ session_unlock_list();
+
+ lus = trace_ust_create_session(session->path, uid, domain);
if (lus == NULL) {
+ ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
- ret = mkdir_recursive(lus->path, S_IRWXU | S_IRWXG,
+ ret = mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG,
geteuid(), allowed_group());
if (ret < 0) {
if (ret != -EEXIST) {
ERR("Trace directory creation error");
+ ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
}
- /* Create session on the UST tracer */
- ret = ustctl_create_session(lus);
- if (ret < 0) {
+ /* The domain type dictate different actions on session creation */
+ switch (domain->type) {
+ case LTTNG_DOMAIN_UST:
+ /* No ustctl for the global UST domain */
+ break;
+ default:
goto error;
}
+ session->ust_session = lus;
- return 0;
+ return LTTCOMM_OK;
error:
free(lus);
}
/* Set kernel consumer socket fd */
- if (kconsumerd_cmd_sock) {
- session->kernel_session->consumer_fd = kconsumerd_cmd_sock;
+ if (kconsumer_data.cmd_sock) {
+ session->kernel_session->consumer_fd = kconsumer_data.cmd_sock;
}
ret = mkdir_recursive(session->kernel_session->trace_path,
case LTTNG_KERNEL_NOOP:
events[i].type = LTTNG_EVENT_NOOP;
break;
- case LTTNG_KERNEL_SYSCALLS:
- events[i].type = LTTNG_EVENT_SYSCALLS;
+ case LTTNG_KERNEL_SYSCALL:
+ events[i].type = LTTNG_EVENT_SYSCALL;
+ break;
+ case LTTNG_KERNEL_ALL:
+ assert(0);
break;
}
i++;
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ case LTTNG_DOMAIN_UST_PID:
+ break;
default:
- /* TODO: Userspace tracing */
- ret = LTTCOMM_NOT_IMPLEMENTED;
+ ret = LTTCOMM_UNKNOWN_DOMAIN;
goto error;
}
return ret;
}
+/*
+ * Copy channel from attributes and set it in the application channel list.
+ */
+/*
+static int copy_ust_channel_to_app(struct ltt_ust_session *usess,
+ struct lttng_channel *attr, struct ust_app *app)
+{
+ int ret;
+ struct ltt_ust_channel *uchan, *new_chan;
+
+ uchan = trace_ust_get_channel_by_key(usess->channels, attr->name);
+ if (uchan == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ new_chan = trace_ust_create_channel(attr, usess->path);
+ if (new_chan == NULL) {
+ PERROR("malloc ltt_ust_channel");
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ ret = channel_ust_copy(new_chan, uchan);
+ if (ret < 0) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+error:
+ return ret;
+}
+*/
+
/*
* Command LTTNG_ENABLE_CHANNEL processed by the client thread.
*/
-static int cmd_enable_channel(struct ltt_session *session, int domain,
- char *channel_name, struct lttng_channel *attr)
+static int cmd_enable_channel(struct ltt_session *session,
+ struct lttng_domain *domain, struct lttng_channel *attr)
{
int ret;
- struct ltt_kernel_channel *kchan;
+ struct ltt_ust_session *usess = session->ust_session;
- switch (domain) {
- case LTTNG_DOMAIN_KERNEL:
- kchan = trace_kernel_get_channel_by_name(channel_name,
- session->kernel_session);
- if (kchan == NULL) {
- ret = channel_kernel_create(session->kernel_session,
- channel_name, attr, kernel_poll_pipe[1]);
- } else {
- ret = channel_kernel_enable(session->kernel_session, kchan);
- }
+ DBG("Enabling channel %s for session %s", session->name, attr->name);
- if (ret != LTTCOMM_OK) {
+ switch (domain->type) {
+ case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+
+ kchan = trace_kernel_get_channel_by_name(attr->name,
+ session->kernel_session);
+ if (kchan == NULL) {
+ ret = channel_kernel_create(session->kernel_session,
+ attr, kernel_poll_pipe[1]);
+ } else {
+ ret = channel_kernel_enable(session->kernel_session, kchan);
+ }
+
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+
+ kernel_wait_quiescent(kernel_tracer_fd);
+ break;
+ }
+ case LTTNG_DOMAIN_UST:
+ {
+ struct ltt_ust_channel *uchan;
+
+ DBG2("Enabling channel for LTTNG_DOMAIN_UST");
+
+ /* Get channel in global UST domain HT */
+ uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
+ attr->name);
+ if (uchan == NULL) {
+ uchan = trace_ust_create_channel(attr, usess->pathname);
+ if (uchan == NULL) {
+ ret = LTTCOMM_UST_CHAN_FAIL;
goto error;
}
+ rcu_read_lock();
+ hashtable_add_unique(usess->domain_global.channels, &uchan->node);
+ rcu_read_unlock();
+ DBG2("UST channel %s added to global domain HT", attr->name);
+ } else {
+ ret = LTTCOMM_UST_CHAN_EXIST;
+ goto error;
+ }
- kernel_wait_quiescent(kernel_tracer_fd);
- break;
- default:
- /* TODO: Userspace tracing */
- ret = LTTCOMM_NOT_IMPLEMENTED;
+ ret = ust_app_add_channel(usess, uchan);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+
+ break;
+ }
+ case LTTNG_DOMAIN_UST_PID:
+ {
+ /*
+ int sock;
+ struct ltt_ust_channel *uchan;
+ struct ltt_ust_session *usess;
+ struct ust_app *app;
+
+ usess = trace_ust_get_session_by_pid(&session->ust_session_list,
+ domain->attr.pid);
+ if (usess == NULL) {
+ ret = LTTCOMM_UST_CHAN_NOT_FOUND;
+ goto error;
+ }
+
+ app = ust_app_get_by_pid(domain->attr.pid);
+ if (app == NULL) {
+ ret = LTTCOMM_APP_NOT_FOUND;
+ goto error;
+ }
+ sock = app->sock;
+
+ uchan = trace_ust_get_channel_by_name(attr->name, usess);
+ if (uchan == NULL) {
+ ret = channel_ust_create(usess, attr, sock);
+ } else {
+ ret = channel_ust_enable(usess, uchan, sock);
+ }
+
+ if (ret != LTTCOMM_OK) {
goto error;
+ }
+
+ ret = copy_ust_channel_to_app(usess, attr, app);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+
+ DBG("UST channel %s created for app sock %d with pid %d",
+ attr->name, app->sock, domain->attr.pid);
+ */
+ ret = LTTCOMM_NOT_IMPLEMENTED;
+ goto error;
+ }
+ default:
+ ret = LTTCOMM_UNKNOWN_DOMAIN;
+ goto error;
}
ret = LTTCOMM_OK;
char *channel_name, char *event_name)
{
int ret;
- struct ltt_kernel_channel *kchan;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+
kchan = trace_kernel_get_channel_by_name(channel_name,
session->kernel_session);
if (kchan == NULL) {
goto error;
}
- ret = event_kernel_disable(session->kernel_session, kchan, event_name);
+ ret = event_kernel_disable_tracepoint(session->kernel_session, kchan, event_name);
if (ret != LTTCOMM_OK) {
goto error;
}
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ }
+ case LTTNG_DOMAIN_UST:
+ case LTTNG_DOMAIN_UST_EXEC_NAME:
+ case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
default:
- /* TODO: Userspace tracing */
+ /* TODO: Other UST domains */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
if (ret != LTTCOMM_OK) {
goto error;
}
+ break;
+ case LTTNG_DOMAIN_UST:
+ {
+ /*
+ struct ltt_ust_session *usess;
+ cds_list_for_each_entry(usess, &session->ust_session_list.head, list) {
+ ret = context_ust_add(usess, ctx,
+ event_name, channel_name, domain);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
break;
+ */
+ }
default:
- /* TODO: Userspace tracing */
+ /* TODO: UST other domains */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
char *channel_name, struct lttng_event *event)
{
int ret;
- struct ltt_kernel_channel *kchan;
+ struct lttng_channel *attr;
+ struct ltt_ust_session *usess = session->ust_session;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+
kchan = trace_kernel_get_channel_by_name(channel_name,
session->kernel_session);
if (kchan == NULL) {
+ attr = channel_new_default_attr(domain);
+ if (attr == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+ snprintf(attr->name, NAME_MAX, "%s", channel_name);
+
/* This call will notify the kernel thread */
- ret = channel_kernel_create(session->kernel_session, channel_name,
- NULL, kernel_poll_pipe[1]);
+ ret = channel_kernel_create(session->kernel_session,
+ attr, kernel_poll_pipe[1]);
if (ret != LTTCOMM_OK) {
goto error;
}
goto error;
}
- ret = event_kernel_enable(session->kernel_session, kchan, event);
+ ret = event_kernel_enable_tracepoint(session->kernel_session, kchan,
+ event);
if (ret != LTTCOMM_OK) {
goto error;
}
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ }
+ case LTTNG_DOMAIN_UST:
+ {
+ struct ltt_ust_channel *uchan;
+ struct ltt_ust_event *uevent;
+
+ uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
+ channel_name);
+ if (uchan == NULL) {
+ /* TODO: Create default channel */
+ ret = LTTCOMM_UST_CHAN_NOT_FOUND;
+ goto error;
+ }
+
+ uevent = trace_ust_find_event_by_name(uchan->events, event->name);
+ if (uevent == NULL) {
+ uevent = trace_ust_create_event(event);
+ if (uevent == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+ }
+
+ ret = ust_app_add_event(usess, uchan, uevent);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_ENABLE_FAIL;
+ goto error;
+ }
+ break;
+ }
+ case LTTNG_DOMAIN_UST_EXEC_NAME:
+ case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
default:
- /* TODO: Userspace tracing */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
* Command LTTNG_ENABLE_ALL_EVENT processed by the client thread.
*/
static int cmd_enable_event_all(struct ltt_session *session, int domain,
- char *channel_name)
+ char *channel_name, int event_type)
{
int ret;
struct ltt_kernel_channel *kchan;
session->kernel_session);
if (kchan == NULL) {
/* This call will notify the kernel thread */
- ret = channel_kernel_create(session->kernel_session, channel_name,
- NULL, kernel_poll_pipe[1]);
+ ret = channel_kernel_create(session->kernel_session, NULL,
+ kernel_poll_pipe[1]);
if (ret != LTTCOMM_OK) {
goto error;
}
goto error;
}
- ret = event_kernel_enable_all(session->kernel_session,
- kchan, kernel_tracer_fd);
+ switch (event_type) {
+ case LTTNG_KERNEL_SYSCALL:
+ ret = event_kernel_enable_all_syscalls(session->kernel_session,
+ kchan, kernel_tracer_fd);
+ break;
+ case LTTNG_KERNEL_TRACEPOINT:
+ /*
+ * This call enables all LTTNG_KERNEL_TRACEPOINTS and
+ * events already registered to the channel.
+ */
+ ret = event_kernel_enable_all_tracepoints(session->kernel_session,
+ kchan, kernel_tracer_fd);
+ break;
+ case LTTNG_KERNEL_ALL:
+ /* Enable syscalls and tracepoints */
+ ret = event_kernel_enable_all(session->kernel_session,
+ kchan, kernel_tracer_fd);
+ break;
+ default:
+ ret = LTTCOMM_KERN_ENABLE_FAIL;
+ goto error;
+ }
if (ret != LTTCOMM_OK) {
goto error;
}
static int cmd_start_trace(struct ltt_session *session)
{
int ret;
- struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
+ struct ltt_ust_session *usess = session->ust_session;
/* Short cut */
ksession = session->kernel_session;
/* Kernel tracing */
if (ksession != NULL) {
+ struct ltt_kernel_channel *kchan;
+
/* Open kernel metadata */
if (ksession->metadata == NULL) {
ret = kernel_open_metadata(ksession, ksession->trace_path);
kernel_wait_quiescent(kernel_tracer_fd);
}
- /* TODO: Start all UST traces */
+ ret = ust_app_start_trace(usess);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_START_FAIL;
+ goto error;
+ }
ret = LTTCOMM_OK;
int ret;
struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
+ //struct ltt_ust_session *usess;
+ //struct ltt_ust_channel *ustchan;
/* Short cut */
ksession = session->kernel_session;
kernel_wait_quiescent(kernel_tracer_fd);
}
- /* TODO : User-space tracer */
+#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");
+ }
+ }
+
+ ret = ustctl_stop_session(usess->sock, usess->handle);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_STOP_FAIL;
+ goto error;
+ }
+
+ ustctl_wait_quiescent(usess->sock);
+ }
+#endif
ret = LTTCOMM_OK;
perror("write kernel poll pipe");
}
- ret = session_destroy(name);
+ ret = session_destroy(session);
return ret;
}
nb_dom++;
}
- nb_dom += session->ust_session_list.count;
+ /* TODO: User-space tracer domain support */
*domains = malloc(nb_dom * sizeof(struct lttng_domain));
if (*domains == NULL) {
(*domains)[0].type = LTTNG_DOMAIN_KERNEL;
- /* TODO: User-space tracer domain support */
-
return nb_dom;
error:
list_lttng_channels(session, *channels);
+ /* TODO UST support */
+
return nb_chan;
error:
static int process_client_msg(struct command_ctx *cmd_ctx)
{
int ret = LTTCOMM_OK;
- int need_kernel_session = 1;
+ int need_tracing_session = 1;
DBG("Processing client command %d", cmd_ctx->lsm->cmd_type);
/*
* Check for command that don't needs to allocate a returned payload. We do
- * this here so we don't have to make the call for no payload" at each
+ * this here so we don't have to make the call for no payload at each
* command.
*/
switch(cmd_ctx->lsm->cmd_type) {
case LTTNG_CREATE_SESSION:
case LTTNG_LIST_SESSIONS:
case LTTNG_LIST_TRACEPOINTS:
- need_kernel_session = 0;
+ need_tracing_session = 0;
break;
default:
DBG("Getting session %s by name", cmd_ctx->lsm->session.name);
+ session_lock_list();
cmd_ctx->session = session_find_by_name(cmd_ctx->lsm->session.name);
+ session_unlock_list();
if (cmd_ctx->session == NULL) {
if (cmd_ctx->lsm->session.name != NULL) {
ret = LTTCOMM_SESS_NOT_FOUND;
}
/* Need a session for kernel command */
- if (need_kernel_session) {
+ if (need_tracing_session) {
if (cmd_ctx->session->kernel_session == NULL) {
ret = create_kernel_session(cmd_ctx->session);
if (ret < 0) {
}
/* Start the kernel consumer daemon */
- if (kconsumerd_pid == 0 &&
+ pthread_mutex_lock(&kconsumer_data.pid_mutex);
+ if (kconsumer_data.pid == 0 &&
cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
- ret = start_kconsumerd();
+ pthread_mutex_unlock(&kconsumer_data.pid_mutex);
+ ret = start_consumerd(&kconsumer_data);
if (ret < 0) {
ret = LTTCOMM_KERN_CONSUMER_FAIL;
goto error;
}
}
+ pthread_mutex_unlock(&kconsumer_data.pid_mutex);
}
break;
+ case LTTNG_DOMAIN_UST:
+ {
+ if (need_tracing_session) {
+ if (cmd_ctx->session->ust_session == NULL) {
+ ret = create_ust_session(cmd_ctx->session,
+ &cmd_ctx->lsm->domain);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
+ /* Start the kernel consumer daemon */
+ pthread_mutex_lock(&ustconsumer_data.pid_mutex);
+ if (ustconsumer_data.pid == 0 &&
+ cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
+ pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
+ ret = start_consumerd(&ustconsumer_data);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_CONSUMER_FAIL;
+ goto error;
+ }
+
+ cmd_ctx->session->ust_session->consumer_fd =
+ ustconsumer_data.cmd_sock;
+ }
+ pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
+ }
+ break;
+ }
default:
- /* TODO Userspace tracer */
break;
}
}
case LTTNG_DISABLE_ALL_EVENT:
{
- DBG("Disabling all kernel 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);
}
case LTTNG_ENABLE_CHANNEL:
{
- ret = cmd_enable_channel(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.enable.channel_name,
+ ret = cmd_enable_channel(cmd_ctx->session, &cmd_ctx->lsm->domain,
&cmd_ctx->lsm->u.channel.chan);
break;
}
}
case LTTNG_ENABLE_ALL_EVENT:
{
- DBG("Enabling all kernel event");
+ DBG("Enabling all events");
ret = cmd_enable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.enable.channel_name);
+ cmd_ctx->lsm->u.enable.channel_name,
+ cmd_ctx->lsm->u.enable.event.type);
break;
}
case LTTNG_LIST_TRACEPOINTS:
case LTTNG_LIST_EVENTS:
{
size_t nb_event;
- struct lttng_event *events;
+ struct lttng_event *events = NULL;
nb_event = cmd_list_events(cmd_ctx->session,
cmd_ctx->lsm->u.list.channel_name, &events);
DBG("[thread] Manage client started");
+ rcu_register_thread();
+
ret = lttcomm_listen_unix_sock(client_sock);
if (ret < 0) {
goto error;
// TODO: Validate cmd_ctx including sanity check for
// security purpose.
+ rcu_thread_online();
/*
* This function dispatch the work to the kernel or userspace tracer
* libs and fill the lttcomm_lttng_msg data structure of all the needed
* everything this function may needs.
*/
ret = process_client_msg(cmd_ctx);
+ rcu_thread_offline();
if (ret < 0) {
/*
* TODO: Inform client somehow of the fatal error. At
DBG("Sending response (size: %d, retcode: %s)",
cmd_ctx->lttng_msg_size,
- lttng_get_readable_code(cmd_ctx->llm->ret_code));
+ lttng_strerror(-cmd_ctx->llm->ret_code));
ret = send_unix_sock(sock, cmd_ctx->llm, cmd_ctx->lttng_msg_size);
if (ret < 0) {
ERR("Failed to send data back to client");
lttng_poll_clean(&events);
clean_command_ctx(&cmd_ctx);
+
+ rcu_unregister_thread();
return NULL;
}
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, " -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");
fprintf(stderr, " -S, --sig-parent Send SIGCHLD to parent pid to notify readiness.\n");
fprintf(stderr, " -q, --quiet No output at all.\n");
fprintf(stderr, " -v, --verbose Verbose mode. Activate DBG() macro.\n");
- fprintf(stderr, " --verbose-kconsumerd Verbose mode for kconsumerd. Activate DBG() macro.\n");
+ fprintf(stderr, " --verbose-consumer Verbose mode for consumer. Activate DBG() macro.\n");
}
/*
static struct option long_options[] = {
{ "client-sock", 1, 0, 'c' },
{ "apps-sock", 1, 0, 'a' },
- { "kconsumerd-cmd-sock", 1, 0, 0 },
- { "kconsumerd-err-sock", 1, 0, 0 },
+ { "kconsumerd-cmd-sock", 1, 0, 'C' },
+ { "kconsumerd-err-sock", 1, 0, 'E' },
+ { "ustconsumerd-cmd-sock", 1, 0, 'D' },
+ { "ustconsumerd-err-sock", 1, 0, 'F' },
{ "daemonize", 0, 0, 'd' },
{ "sig-parent", 0, 0, 'S' },
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
{ "quiet", 0, 0, 'q' },
{ "verbose", 0, 0, 'v' },
- { "verbose-kconsumerd", 0, 0, 'Z' },
+ { "verbose-consumer", 0, 0, 'Z' },
{ NULL, 0, 0, 0 }
};
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:E:C:Z",
+ c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:C:E:D:F:Z",
long_options, &option_index);
if (c == -1) {
break;
opt_sig_parent = 1;
break;
case 'E':
- snprintf(kconsumerd_err_unix_sock_path, PATH_MAX, "%s", optarg);
+ snprintf(kconsumer_data.err_unix_sock_path, PATH_MAX, "%s", optarg);
break;
case 'C':
- snprintf(kconsumerd_cmd_unix_sock_path, PATH_MAX, "%s", optarg);
+ 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);
+ break;
+ case 'D':
+ snprintf(ustconsumer_data.cmd_unix_sock_path, PATH_MAX, "%s", optarg);
break;
case 'q':
opt_quiet = 1;
opt_verbose += 1;
break;
case 'Z':
- opt_verbose_kconsumerd += 1;
+ opt_verbose_consumer += 1;
break;
default:
/* Unknown option or other error.
perror("chown");
}
- /* kconsumerd error socket path */
- ret = chown(kconsumerd_err_unix_sock_path, 0, gid);
+ /* kconsumer error socket path */
+ ret = chown(kconsumer_data.err_unix_sock_path, 0, gid);
+ if (ret < 0) {
+ ERR("Unable to set group on %s", kconsumer_data.err_unix_sock_path);
+ perror("chown");
+ }
+
+ /* ustconsumer error socket path */
+ ret = chown(ustconsumer_data.err_unix_sock_path, 0, gid);
if (ret < 0) {
- ERR("Unable to set group on %s", kconsumerd_err_unix_sock_path);
+ ERR("Unable to set group on %s", ustconsumer_data.err_unix_sock_path);
perror("chown");
}
* Setup sockets and directory needed by the kconsumerd communication with the
* session daemon.
*/
-static int set_kconsumerd_sockets(void)
+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(kconsumerd_err_unix_sock_path) == 0) {
- snprintf(kconsumerd_err_unix_sock_path, PATH_MAX,
- KCONSUMERD_ERR_SOCK_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);
}
- if (strlen(kconsumerd_cmd_unix_sock_path) == 0) {
- snprintf(kconsumerd_cmd_unix_sock_path, PATH_MAX,
- KCONSUMERD_CMD_SOCK_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);
}
- ret = mkdir(KCONSUMERD_PATH, S_IRWXU | S_IRWXG);
+ ret = mkdir(path, S_IRWXU | S_IRWXG);
if (ret < 0) {
if (errno != EEXIST) {
- ERR("Failed to create " KCONSUMERD_PATH);
+ ERR("Failed to create %s", path);
goto error;
}
ret = 0;
}
/* Create the kconsumerd error unix socket */
- kconsumerd_err_sock =
- lttcomm_create_unix_sock(kconsumerd_err_unix_sock_path);
- if (kconsumerd_err_sock < 0) {
- ERR("Create unix sock failed: %s", kconsumerd_err_unix_sock_path);
+ consumer_data->err_sock =
+ lttcomm_create_unix_sock(consumer_data->err_unix_sock_path);
+ if (consumer_data->err_sock < 0) {
+ ERR("Create unix sock failed: %s", consumer_data->err_unix_sock_path);
ret = -1;
goto error;
}
/* File permission MUST be 660 */
- ret = chmod(kconsumerd_err_unix_sock_path,
+ ret = chmod(consumer_data->err_unix_sock_path,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (ret < 0) {
- ERR("Set file permissions failed: %s", kconsumerd_err_unix_sock_path);
+ ERR("Set file permissions failed: %s", consumer_data->err_unix_sock_path);
perror("chmod");
goto error;
}
void *status;
const char *home_path;
+ rcu_register_thread();
+
/* Create thread quit pipe */
if ((ret = init_thread_quit_pipe()) < 0) {
goto error;
* kernel tracer.
*/
if (is_root) {
- ret = set_kconsumerd_sockets();
+ ret = set_consumer_sockets(&kconsumer_data);
if (ret < 0) {
goto exit;
}
+ ret = set_consumer_sockets(&ustconsumer_data);
+ if (ret < 0) {
+ goto exit;
+ }
/* Setup kernel tracer */
init_kernel_tracer();
/* Init UST command queue. */
cds_wfq_init(&ust_cmd_queue.queue);
+ /* Init UST app hash table */
+ ust_app_ht_alloc();
+
/*
* Get session list pointer. This pointer MUST NOT be free(). This list is
* statically declared in session.c
goto error; /* join error, exit without cleanup */
}
- ret = join_kconsumerd_thread();
+ ret = join_consumer_thread(&kconsumer_data);
if (ret != 0) {
- perror("join_kconsumerd");
+ perror("join_consumer");
goto error; /* join error, exit without cleanup */
}
/*
* cleanup() is called when no other thread is running.
*/
+ rcu_thread_online();
cleanup();
+ rcu_thread_offline();
+ rcu_unregister_thread();
if (!ret)
exit(EXIT_SUCCESS);
error: