LTTCOMM_KERN_DIR_EXIST, /* Kernel trace directory exist */
LTTCOMM_KERN_NO_SESSION, /* No kernel session found */
LTTCOMM_KERN_LIST_FAIL, /* Kernel listing events failed */
+ LTTCOMM_UST_SESS_FAIL, /* UST create session failed */
KCONSUMERD_COMMAND_SOCK_READY, /* when kconsumerd command socket ready */
KCONSUMERD_SUCCESS_RECV_FD, /* success on receiving fds */
KCONSUMERD_ERROR_RECV_FD, /* error on receiving fds */
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_DIR_EXIST) ] = "Kernel trace directory already exist",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_NO_SESSION) ] = "No kernel session found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_LIST_FAIL) ] = "Listing kernel events failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_SESS_FAIL) ] = "UST create session failed",
[ LTTCOMM_ERR_INDEX(KCONSUMERD_COMMAND_SOCK_READY) ] = "Kconsumerd command socket ready",
[ LTTCOMM_ERR_INDEX(KCONSUMERD_SUCCESS_RECV_FD) ] = "Kconsumerd success on receiving fds",
[ LTTCOMM_ERR_INDEX(KCONSUMERD_ERROR_RECV_FD) ] = "Kconsumerd error on receiving fds",
ltt_sessiond_SOURCES = utils.c utils.h \
trace-kernel.c trace-kernel.h \
trace-ust.c trace-ust.h \
- session.c session.h \
traceable-app.c traceable-app.h \
+ ust-comm.c ust-comm.h \
ust-ctl.c ust-ctl.h \
kernel-ctl.c kernel-ctl.h \
context.c context.h \
futex.c futex.h \
- ust-comm.c ust-comm.h \
+ session.c session.h \
ltt-sessiond.h main.c
# link on liblttngctl for check if sessiond is already alive.
#include "traceable-app.h"
#include "ust-ctl.h"
#include "utils.h"
-#include "ust-comm.h"
+#include "ust-ctl.h"
/* Const values */
const char default_home_dir[] = DEFAULT_HOME_DIR;
}
#ifdef DISABLED
-/*
- * Return a socket connected to the libust communication socket of the
- * application identified by the pid.
- *
- * If the pid is not found in the traceable list, return -1 to indicate error.
- */
-static int ust_connect_app(pid_t pid)
-{
- int sock;
- struct ltt_traceable_app *lta;
-
- DBG("Connect to application pid %d", pid);
-
- lta = find_app_by_pid(pid);
- if (lta == NULL) {
- /* App not found */
- DBG("Application pid %d not found", pid);
- return -1;
- }
-
- sock = ustctl_connect_pid(lta->pid);
- if (sock < 0) {
- ERR("Fail connecting to the PID %d", pid);
- }
-
- return sock;
-}
-
/*
* Notify apps by writing 42 to a named pipe using name. Every applications
* waiting for a ltt-sessiond will be notified and re-register automatically to
*
* The first two fds must be there at all time.
*/
-static int update_apps_cmd_pollfd(unsigned int nb_fd, struct pollfd **pollfd)
+static int update_apps_cmd_pollfd(unsigned int nb_fd, unsigned int old_nb_fd,
+ struct pollfd **pollfd)
{
+ int i, count;
+ struct pollfd *old_pollfd = NULL;
+
/* Can't accept pollfd less than 2 */
if (nb_fd < 2) {
goto end;
}
- *pollfd = realloc(*pollfd, nb_fd * sizeof(struct pollfd));
+ if (*pollfd) {
+ /* Save pointer */
+ old_pollfd = *pollfd;
+ }
+
+ *pollfd = malloc(nb_fd * sizeof(struct pollfd));
if (*pollfd == NULL) {
- perror("realloc manage apps pollfd");
+ perror("malloc manage apps pollfd");
goto error;
}
(*pollfd)[1].fd = apps_cmd_pipe[0];
(*pollfd)[1].events = POLLIN;
+ /* Start count after the two pipes below */
+ count = 2;
+ for (i = 2; i < old_nb_fd; i++) {
+ /* Add to new pollfd */
+ if (old_pollfd[i].fd != -1) {
+ (*pollfd)[count].fd = old_pollfd[i].fd;
+ (*pollfd)[count].events = POLLHUP | POLLNVAL | POLLERR;
+ count++;
+ }
+
+ if (count > nb_fd) {
+ ERR("Updating poll fd wrong size");
+ goto error;
+ }
+ }
+
+ /* Destroy old pollfd */
+ free(old_pollfd);
+
DBG("Apps cmd pollfd realloc of size %d", nb_fd);
end:
return 0;
error:
+ /* Destroy old pollfd */
+ free(old_pollfd);
return -1;
}
-/*
- * Send registration done packet to the application.
- */
-static int send_ust_register_done(int sock)
-{
- struct lttcomm_ust_msg lum;
-
- DBG("Sending register done command to %d", sock);
-
- lum.cmd = LTTNG_UST_REGISTER_DONE;
- lum.handle = LTTNG_UST_ROOT_HANDLE;
-
- return ustcomm_send_command(sock, &lum);
-}
-
/*
* This thread manage application communication.
*/
/* The pollfd struct must be updated */
if (update_poll_flag) {
- ret = update_apps_cmd_pollfd(nb_fd, &pollfd);
+ ret = update_apps_cmd_pollfd(nb_fd, ARRAY_SIZE(pollfd), &pollfd);
if (ret < 0) {
/* malloc failed so we quit */
goto error;
}
+
if (ust_cmd.sock != -1) {
/* Update pollfd with the new UST socket */
DBG("Adding sock %d to apps cmd pollfd", ust_cmd.sock);
pollfd[nb_fd - 1].fd = ust_cmd.sock;
- pollfd[nb_fd - 1].events = POLLHUP | POLLNVAL;
+ pollfd[nb_fd - 1].events = POLLHUP | POLLNVAL | POLLERR;
ust_cmd.sock = -1;
}
}
/* Thread quit pipe has been closed. Killing thread. */
if (pollfd[0].revents == POLLNVAL) {
goto error;
- } else if (pollfd[1].revents == POLLERR) {
- ERR("Apps command pipe poll error");
- goto error;
- } else if (pollfd[1].revents == POLLIN) {
- /* Empty pipe */
- ret = read(apps_cmd_pipe[0], &ust_cmd, sizeof(ust_cmd));
- if (ret < 0 || ret < sizeof(ust_cmd)) {
- perror("read apps cmd pipe");
+ } else {
+ /* apps_cmd_pipe pipe events */
+ switch (pollfd[1].revents) {
+ case POLLERR:
+ ERR("Apps command pipe poll error");
goto error;
- }
+ case POLLIN:
+ /* Empty pipe */
+ ret = read(apps_cmd_pipe[0], &ust_cmd, sizeof(ust_cmd));
+ if (ret < 0 || ret < sizeof(ust_cmd)) {
+ perror("read apps cmd pipe");
+ goto error;
+ }
- /* Register applicaton to the session daemon */
- ret = register_traceable_app(&ust_cmd.reg_msg, ust_cmd.sock);
- if (ret < 0) {
- /* Only critical ENOMEM error can be returned here */
- goto error;
- }
+ /* Register applicaton to the session daemon */
+ ret = register_traceable_app(&ust_cmd.reg_msg, ust_cmd.sock);
+ if (ret < 0) {
+ /* Only critical ENOMEM error can be returned here */
+ goto error;
+ }
- ret = send_ust_register_done(ust_cmd.sock);
- if (ret < 0) {
- /*
- * If the registration is not possible, we simply unregister
- * the apps and continue
- */
- unregister_traceable_app(ust_cmd.sock);
+ ret = ustctl_register_done(ust_cmd.sock);
+ if (ret < 0) {
+ /*
+ * If the registration is not possible, we simply unregister
+ * the apps and continue
+ */
+ unregister_traceable_app(ust_cmd.sock);
+ }
+ break;
}
}
for (i = 2; i < count; i++) {
/* Apps socket is closed/hungup */
switch (pollfd[i].revents) {
- case POLLNVAL:
+ case POLLERR:
case POLLHUP:
+ case POLLNVAL:
/* Pipe closed */
unregister_traceable_app(pollfd[i].fd);
+ /* Indicate to remove this fd from the pollfd */
+ pollfd[i].fd = -1;
nb_fd--;
+ break;
}
}
return NULL;
}
+/*
+ * Create an UST session and add it to the session ust list.
+ */
+static int create_ust_session(pid_t pid, struct ltt_session *session)
+{
+ int ret = -1;
+ struct ltt_ust_session *lus;
+
+ DBG("Creating UST session");
+
+ lus = trace_ust_create_session(session->path, pid);
+ if (lus == NULL) {
+ goto error;
+ }
+
+ ret = mkdir_recursive(lus->path, S_IRWXU | S_IRWXG,
+ geteuid(), allowed_group());
+ if (ret < 0) {
+ if (ret != -EEXIST) {
+ ERR("Trace directory creation error");
+ goto error;
+ }
+ }
+
+ /* Create session on the UST tracer */
+ ret = ustctl_create_session(lus);
+ if (ret < 0) {
+ goto error;
+ }
+
+ return 0;
+
+error:
+ free(lus);
+ return ret;
+}
+
/*
* Create a kernel tracer session then create the default channel.
*/
goto error;
}
}
-
/* Need a session for kernel command */
switch (cmd_ctx->lsm->cmd_type) {
case LTTNG_CALIBRATE:
ret = LTTCOMM_KERN_SESS_FAIL;
goto error;
}
-
/* Start the kernel consumer daemon */
-
if (kconsumerd_pid == 0 &&
cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
ret = start_kconsumerd();
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ case LTTNG_DOMAIN_UST_PID:
+ break;
default:
- /* TODO: Userspace tracing */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
nb_dom++;
}
- nb_dom += cmd_ctx->session->ust_trace_count;
+ nb_dom += cmd_ctx->session->ust_session_list.count;
ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_domain) * nb_dom);
if (ret < 0) {
/* Init kernel session */
new_session->kernel_session = NULL;
- /* Init list */
- CDS_INIT_LIST_HEAD(&new_session->ust_traces);
+ /* Init UST session list */
+ CDS_INIT_LIST_HEAD(&new_session->ust_session_list.head);
- /* Set trace list counter */
- new_session->ust_trace_count = 0;
+ /* Init lock */
+ pthread_mutex_init(&new_session->lock, NULL);
/* Add new session to the session list */
lock_session_list();
add_session_list(new_session);
unlock_session_list();
- /* Init lock */
- pthread_mutex_init(&new_session->lock, NULL);
-
- DBG("Tracing session %s created in %s", new_session->name, new_session->path);
+ DBG("Tracing session %s created in %s", name, path);
return 0;
char *name;
char *path;
struct ltt_kernel_session *kernel_session;
- struct cds_list_head ust_traces;
- unsigned int ust_trace_count;
+ struct ltt_ust_session_list ust_session_list;
/*
* Protect any read/write on this session data structure. This lock must be
* acquired *before* using any public functions declared below. Use
#include "trace-ust.h"
+/*
+ * Return an UST session by traceable app PID.
+ */
+struct ltt_ust_session *trace_ust_get_session_by_pid(pid_t pid,
+ struct ltt_ust_session_list *session_list)
+{
+ struct ltt_ust_session *lus;
+
+ cds_list_for_each_entry(lus, &session_list->head, list) {
+ if (lus->app->pid == pid) {
+ DBG("Found UST session by pid %d", pid);
+ return lus;
+ }
+ }
+
+ return NULL;
+}
+
/*
* Find the channel name for the given ust session.
*/
*
* Return pointer to structure or NULL.
*/
-struct ltt_ust_session *trace_ust_create_session(void)
+struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid)
{
+ int ret;
struct ltt_ust_session *lus;
/* Allocate a new ltt ust session */
lus->uconsumer_fds_sent = 0;
lus->path = NULL;
lus->metadata = NULL;
+ lus->app = NULL; /* TODO: Search app by PID */
lus->channels.count = 0;
CDS_INIT_LIST_HEAD(&lus->channels.head);
+ /* Set session path */
+ ret = asprintf(&lus->path, "%s/ust_%d", path, pid);
+ if (ret < 0) {
+ perror("asprintf kernel traces path");
+ goto error;
+ }
+
return lus;
error:
#include <lttng/lttng.h>
#include <lttng-ust.h>
+#include "traceable-app.h"
+
+/*
+ * UST session list.
+ */
+struct ltt_ust_session_list {
+ unsigned int count;
+ struct cds_list_head head;
+};
+
/* UST event list */
struct ltt_ust_event_list {
unsigned int count;
int enabled;
int uconsumer_fds_sent;
char *path;
+ struct ltt_traceable_app *app;
struct ltt_ust_metadata *metadata;
struct ltt_ust_channel_list channels;
+ struct cds_list_head list;
};
/*
char *name, struct ltt_ust_channel *channel);
struct ltt_ust_channel *trace_ust_get_channel_by_name(
char *name, struct ltt_ust_session *session);
+struct ltt_ust_session *trace_ust_get_session_by_pid(pid_t pid,
+ struct ltt_ust_session_list *session_list);
/*
* Create functions malloc() the data structure.
*/
-struct ltt_ust_session *trace_ust_create_session(void);
+struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid);
struct ltt_ust_channel *trace_ust_create_channel(char *name, char *path,
struct lttng_ust_channel *attr);
struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev);
return NULL;
}
+/*
+ * Iterate over the traceable apps list and return a pointer or NULL if not
+ * found.
+ */
+struct ltt_traceable_app *traceable_app_get_by_pid(pid_t pid)
+{
+ struct ltt_traceable_app *iter;
+
+ cds_list_for_each_entry(iter, <t_traceable_app_list.head, list) {
+ if (iter->pid == pid) {
+ /* Found */
+ return iter;
+ }
+ }
+
+ return NULL;
+}
+
/*
* Using pid and uid (of the app), allocate a new ltt_traceable_app struct and
* add it to the global traceable app list.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <stdlib.h>
+
#include <lttngerr.h>
#include "ust-comm.h"
* Send msg containing a command to an UST application via sock and wait for
* the reply.
*
- * Return -1 on error or if reply fails else return 0.
+ * Return the replied structure or NULL.
*/
-int ustcomm_send_command(int sock, struct lttcomm_ust_msg *msg)
+struct lttcomm_ust_reply *ustcomm_send_command(int sock,
+ struct lttcomm_ust_msg *msg)
{
ssize_t len;
- struct lttcomm_ust_reply reply;
+ struct lttcomm_ust_reply *reply;
+
+ /* Extra safety */
+ if (msg == NULL || sock < 0) {
+ goto error;
+ }
DBG("Sending UST command %d to sock %d", msg->cmd, sock);
goto error;
}
- DBG("Receiving UST reply on sock %d", sock);
-
- /* Get UST reply */
- len = lttcomm_recv_unix_sock(sock, &reply, sizeof(reply));
- if (len < 0) {
+ reply = malloc(sizeof(struct lttcomm_ust_reply));
+ if (reply == NULL) {
+ perror("malloc ust reply");
goto error;
}
- if (reply.ret_code != LTTCOMM_OK) {
+ DBG("Receiving UST reply on sock %d", sock);
+
+ /* Get UST reply */
+ len = lttcomm_recv_unix_sock(sock, reply, sizeof(*reply));
+ if (len < 0 || len < sizeof(*reply)) {
goto error;
}
- return 0;
+ return reply;
error:
- return -1;
+ return NULL;
}
#include <lttng-sessiond-comm.h>
-int ustcomm_send_command(int sock, struct lttcomm_ust_msg *msg);
+struct lttcomm_ust_reply *ustcomm_send_command(int sock,
+ struct lttcomm_ust_msg *msg);
#endif /* _LTT_UST_COMM_H */
*/
#define _GNU_SOURCE
-#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <lttng-sessiond-comm.h>
-#include "lttngerr.h"
-#include "ust-ctl.h"
-
-#ifdef DISABLED
-/*
- * find_session_ust_trace_by_pid
- *
- * Iterate over the session ust_traces and
- * return a pointer or NULL if not found.
- */
-static struct ltt_ust_trace *find_session_ust_trace_by_pid(
- struct ltt_session *session, pid_t pid)
-{
- struct ltt_ust_trace *iter;
+#include <lttngerr.h>
- cds_list_for_each_entry(iter, &session->ust_traces, list) {
- if (iter->pid == pid) {
- /* Found */
- return iter;
- }
- }
-
- return NULL;
-}
-
-/*
- * get_trace_count_per_session
- *
- * Return the total count of traces (ust and kernel)
- * for the specified session.
- */
-int get_trace_count_per_session(struct ltt_session *session)
-{
- return session->ust_trace_count;
-}
+#include "ust-comm.h"
+#include "ust-ctl.h"
/*
- * get_traces_per_session
- *
- * Fill the lttng_trace array of all the
- * available trace of the session.
+ * Send registration done packet to the application.
*/
-/*
-void get_traces_per_session(struct ltt_session *session, struct lttng_trace *traces)
+int ustctl_register_done(int sock)
{
- int i = 0;
- struct ltt_ust_trace *ust_iter;
- struct lttng_trace trace;
-
- DBG("Getting userspace traces for session %s", session->name);
-
- cds_list_for_each_entry(ust_iter, &session->ust_traces, list) {
- trace.type = USERSPACE;
- trace.pid = ust_iter->pid;
- strncpy(trace.name, ust_iter->name, sizeof(trace.name));
- trace.name[sizeof(trace.name) - 1] = '\0';
- memcpy(&traces[i], &trace, sizeof(trace));
- memset(&trace, 0, sizeof(trace));
- i++;
- }
-
- DBG("Getting kernel traces for session %s", session->name);
-
- if (session->kern_session_count > 0) {
- trace.type = KERNEL;
- strncpy(trace.name, "kernel", sizeof(trace.name));
- trace.name[sizeof(trace.name) - 1] = '\0';
- memcpy(&traces[i], &trace, sizeof(trace));
- }
-}
-*/
+ struct lttcomm_ust_msg command;
+ struct lttcomm_ust_reply *reply;
-/*
- * ust_create_trace
- *
- * Create an userspace trace using pid.
- * This trace is then appended to the current session
- * ust trace list.
- */
-int ust_create_trace(struct command_ctx *cmd_ctx)
-{
- int ret;
- struct ltt_ust_trace *trace;
+ DBG("Sending register done command to %d", sock);
- DBG("Creating trace for pid %d", cmd_ctx->lsm->pid);
+ command.cmd = LTTNG_UST_REGISTER_DONE;
+ command.handle = LTTNG_UST_ROOT_HANDLE;
- trace = malloc(sizeof(struct ltt_ust_trace));
- if (trace == NULL) {
- perror("malloc");
- ret = -1;
+ reply = ustcomm_send_command(sock, &command);
+ if (reply == NULL) {
goto error;
}
- /* Init */
- trace->pid = cmd_ctx->lsm->pid;
- trace->shmid = 0;
- /* NOTE: to be removed. Trace name will no longer be
- * required for LTTng userspace tracer. For now, we set it
- * to 'auto' for API compliance.
- */
- snprintf(trace->name, 5, "auto");
-
- ret = ustctl_create_trace(cmd_ctx->ust_sock, trace->name);
- if (ret < 0) {
- ret = LTTCOMM_CREATE_FAIL;
- goto error_create;
- }
-
- /* Check if current session is valid */
- if (cmd_ctx->session) {
- cds_list_add(&trace->list, &cmd_ctx->session->ust_traces);
- cmd_ctx->session->ust_trace_count++;
+ if (reply->ret_code != LTTCOMM_OK) {
+ DBG("Return code: %s", lttcomm_get_readable_code(reply->ret_code));
+ goto error;
}
- return LTTCOMM_OK;
+ return 0;
-error_create:
- free(trace);
error:
- return ret;
+ return -1;
}
/*
- * ust_start_trace
- *
- * Start a trace. This trace, identified by the pid, must be
- * in the current session ust_traces list.
+ * Create an UST session on the tracer.
*/
-int ust_start_trace(struct command_ctx *cmd_ctx)
+int ustctl_create_session(struct ltt_ust_session *session)
{
- int ret;
- struct ltt_ust_trace *trace;
+ struct lttcomm_ust_msg command;
+ struct lttcomm_ust_reply *reply;
- DBG("Starting trace for pid %d", cmd_ctx->lsm->pid);
+ DBG("Creating UST session for app pid:%d", session->app->pid);
- trace = find_session_ust_trace_by_pid(cmd_ctx->session, cmd_ctx->lsm->pid);
- if (trace == NULL) {
- ret = LTTCOMM_NO_TRACE;
- goto error;
- }
+ command.cmd = LTTNG_UST_SESSION;
+ command.handle = LTTNG_UST_ROOT_HANDLE;
- ret = ustctl_start_trace(cmd_ctx->ust_sock, "auto");
- if (ret < 0) {
- ret = LTTCOMM_START_FAIL;
+ reply = ustcomm_send_command(session->app->sock, &command);
+ if (reply == NULL) {
goto error;
}
- ret = LTTCOMM_OK;
-
-error:
- return ret;
-}
-
-/*
- * ust_stop_trace
- *
- * Stop a trace. This trace, identified by the pid, must be
- * in the current session ust_traces list.
- */
-int ust_stop_trace(struct command_ctx *cmd_ctx)
-{
- int ret;
- struct ltt_ust_trace *trace;
-
- DBG("Stopping trace for pid %d", cmd_ctx->lsm->pid);
-
- trace = find_session_ust_trace_by_pid(cmd_ctx->session, cmd_ctx->lsm->pid);
- if (trace == NULL) {
- ret = LTTCOMM_NO_TRACE;
+ if (reply->ret_code != LTTCOMM_OK) {
+ DBG("Return code: %s", lttcomm_get_readable_code(reply->ret_code));
goto error;
}
- ret = ustctl_stop_trace(cmd_ctx->ust_sock, trace->name);
- if (ret < 0) {
- ret = LTTCOMM_STOP_FAIL;
- goto error;
- }
+ /* Save session handle */
+ session->handle = reply->handle;
- ret = LTTCOMM_OK;
+ return 0;
error:
- return ret;
+ return -1;
}
-#endif
-
#ifndef _LTT_UST_CTL_H
#define _LTT_UST_CTL_H
+#include "trace-ust.h"
+
+int ustctl_register_done(int sock);
+int ustctl_create_session(struct ltt_ust_session *session);
+int ustctl_destroy_session(struct ltt_ust_session *session);
+
#endif /* _LTT_UST_CTL_H */
}
/* Basic init session values */
assert(tmp->kernel_session == NULL);
- assert(tmp->ust_trace_count == 0);
+ assert(tmp->ust_session_list.count == 0);
assert(strlen(tmp->path));
assert(strlen(tmp->name));
lock_session(tmp);