ltt-sessiond can now send multiple response to the client for only one
command.
The list traceable apps command was modified accordingly to that
modification and now send one response per pid.
The liblttnctl was also changed to handle multiple reply and the
recvfrom_sessiond internal function is added removing the recv from the
ask_sessiond() function. Fine grained control helps.
Signed-off-by: David Goulet <david.goulet@polymtl.ca>
/* Prototypes */
static int check_tracing_group(const char *grp_name);
static int ask_sessiond(void);
/* Prototypes */
static int check_tracing_group(const char *grp_name);
static int ask_sessiond(void);
+static int recvfrom_sessiond(void);
static int set_session_daemon_path(void);
static void reset_data_struct(void);
static int set_session_daemon_path(void);
static void reset_data_struct(void);
- * Send lttcomm_session_msg to the daemon and wait
- * for the reply. Data replied will be put in llm
+ * Send lttcomm_session_msg to the session daemon.
*
* On success, return 0
* On error, return error code
*
* On success, return 0
* On error, return error code
int ret;
if (!connected) {
int ret;
if (!connected) {
- ret = -ECONNREFUSED;
- goto error;
+ ret = -ENOTCONN;
+ goto end;
}
ret = lttcomm_send_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
}
ret = lttcomm_send_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
- if (ret < 0) {
- goto error;
+
+end:
+ return ret;
+}
+
+/*
+ * recvfrom_sessiond
+ *
+ * Receive data from the sessiond socket.
+ *
+ * On success, return 0
+ * On error, return recv() error code
+ */
+static int recvfrom_sessiond(void)
+{
+ int ret;
+
+ if (!connected) {
+ ret = -ENOTCONN;
+ goto end;
}
ret = lttcomm_recv_unix_sock(sessiond_socket, &llm, sizeof(llm));
if (ret < 0) {
}
ret = lttcomm_recv_unix_sock(sessiond_socket, &llm, sizeof(llm));
if (ret < 0) {
}
/* Check return code */
if (llm.ret_code != LTTCOMM_OK) {
ret = -llm.ret_code;
}
/* Check return code */
if (llm.ret_code != LTTCOMM_OK) {
ret = -llm.ret_code;
*/
size_t lttng_ust_list_apps(pid_t **pids)
{
*/
size_t lttng_ust_list_apps(pid_t **pids)
{
+ int ret, first = 0;
+ size_t size = 0;
+ pid_t *p = NULL;
lsm.cmd_type = UST_LIST_APPS;
lsm.cmd_type = UST_LIST_APPS;
- *pids = llm.u.list_apps.pids;
+ do {
+ ret = recvfrom_sessiond();
+ if (ret < 0) {
+ goto error;
+ }
+
+ if (first == 0) {
+ first = 1;
+ size = llm.num_pckt;
+ p = malloc(sizeof(pid_t) * size);
+ }
+ p[size - llm.num_pckt] = llm.u.list_apps.pid;
+ } while ((llm.num_pckt-1) != 0);
+
+ *pids = p;
- return llm.u.list_apps.size;
[ LTTCOMM_ERR_INDEX(LTTCOMM_UND) ] = "Undefined command",
[ LTTCOMM_ERR_INDEX(LTTCOMM_NO_SESSION) ] = "No session found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_LIST_FAIL) ] = "Unable to list traceable apps",
[ LTTCOMM_ERR_INDEX(LTTCOMM_UND) ] = "Undefined command",
[ LTTCOMM_ERR_INDEX(LTTCOMM_NO_SESSION) ] = "No session found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_LIST_FAIL) ] = "Unable to list traceable apps",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_APPS) ] = "No traceable apps found",
/* Queue size of listen(2) */
#define MAX_LISTEN 10
/* Queue size of listen(2) */
#define MAX_LISTEN 10
-/* Maximum amount of PID the list_apps command
- * can send back to the lttng client.
- */
-#define MAX_APPS_PID 20
-
/* Get the error code index from 0 since
* LTTCOMM_OK start at 1000
*/
/* Get the error code index from 0 since
* LTTCOMM_OK start at 1000
*/
LTTCOMM_SESSION_FAIL, /* Create session fail */
LTTCOMM_START_FAIL, /* Start tracing fail */
LTTCOMM_LIST_FAIL, /* Listing apps fail */
LTTCOMM_SESSION_FAIL, /* Create session fail */
LTTCOMM_START_FAIL, /* Start tracing fail */
LTTCOMM_LIST_FAIL, /* Listing apps fail */
+ LTTCOMM_NO_APPS, /* No traceable application */
LTTCOMM_NR, /* Last element */
};
LTTCOMM_NR, /* Last element */
};
uuid_t session_id;
pid_t pid;
char trace_name[NAME_MAX];
uuid_t session_id;
pid_t pid;
char trace_name[NAME_MAX];
+ /* This flag indicates how many packet are in
+ * the transmission. Ex: If list apps is requested,
+ * and there is 4 pids registered, num_pckt will be 4
+ */
+ unsigned int num_pckt;
union {
/* UST_LIST_APPS */
struct {
union {
/* UST_LIST_APPS */
struct {
- size_t size;
- pid_t pids[MAX_APPS_PID];
static void sighandler(int);
static void daemonize(void);
static void cleanup(void);
static void sighandler(int);
static void daemonize(void);
static void cleanup(void);
+static void copy_common_data(struct lttcomm_lttng_msg *llm, struct lttcomm_session_msg *lsm);
static int check_existing_daemon(void);
static int notify_apps(const char*);
static int connect_app(pid_t);
static int init_daemon_socket(void);
static int check_existing_daemon(void);
static int notify_apps(const char*);
static int connect_app(pid_t);
static int init_daemon_socket(void);
-static struct lttcomm_lttng_msg *process_client_msg(struct lttcomm_session_msg*);
+static int process_client_msg(int sock, struct lttcomm_session_msg*);
+static int send_unix_sock(int sock, void *buf, size_t len);
static void *thread_manage_clients(void *);
static void *thread_manage_apps(void *);
static void *thread_manage_clients(void *);
static void *thread_manage_apps(void *);
static int apps_socket;
static struct ltt_session *current_session;
static int apps_socket;
static struct ltt_session *current_session;
-static int session_count;
+
+/* Number of element for the list below. */
+static unsigned int session_count;
+static unsigned int traceable_app_count;
/* Init session's list */
static struct ltt_session_list ltt_session_list = {
.head = CDS_LIST_HEAD_INIT(ltt_session_list.head),
};
/* Init session's list */
static struct ltt_session_list ltt_session_list = {
.head = CDS_LIST_HEAD_INIT(ltt_session_list.head),
};
+/* Init ust traceabl application's list */
static struct ltt_traceable_app_list ltt_traceable_app_list = {
.head = CDS_LIST_HEAD_INIT(ltt_traceable_app_list.head),
};
static struct ltt_traceable_app_list ltt_traceable_app_list = {
.head = CDS_LIST_HEAD_INIT(ltt_traceable_app_list.head),
};
lta->pid = reg_msg.pid;
lta->uid = reg_msg.uid;
cds_list_add(<a->list, <t_traceable_app_list.head);
lta->pid = reg_msg.pid;
lta->uid = reg_msg.uid;
cds_list_add(<a->list, <t_traceable_app_list.head);
} else {
/* Unregistering */
lta = NULL;
cds_list_for_each_entry(lta, <t_traceable_app_list.head, list) {
if (lta->pid == reg_msg.pid && lta->uid == reg_msg.uid) {
cds_list_del(<a->list);
} else {
/* Unregistering */
lta = NULL;
cds_list_for_each_entry(lta, <t_traceable_app_list.head, list) {
if (lta->pid == reg_msg.pid && lta->uid == reg_msg.uid) {
cds_list_del(<a->list);
+ /* Check to not overflow here */
+ if (traceable_app_count != 0) {
+ traceable_app_count--;
+ }
{
int sock, ret;
struct lttcomm_session_msg lsm;
{
int sock, ret;
struct lttcomm_session_msg lsm;
- struct lttcomm_lttng_msg *llm;
ret = lttcomm_listen_unix_sock(client_socket);
if (ret < 0) {
ret = lttcomm_listen_unix_sock(client_socket);
if (ret < 0) {
}
/* This function dispatch the work to the LTTng or UST libs
}
/* This function dispatch the work to the LTTng or UST libs
- * and make sure that the reply structure (llm) is filled.
- */
- llm = process_client_msg(&lsm);
-
- /* Having a valid lttcomm_lttng_msg struct, reply is sent back
- * to the client directly.
+ * and then sends back the response to the client. This is needed
+ * because there might be more then one lttcomm_lttng_msg to
+ * send out so process_client_msg do both jobs.
- if (llm != NULL) {
- ret = lttcomm_send_unix_sock(sock, llm,
- sizeof(struct lttcomm_lttng_msg));
- free(llm);
- if (ret < 0) {
- continue;
- }
- } else {
- /* The lttcomm_lttng_msg struct was not allocated
- * correctly. Fatal error since the daemon is not able
- * to respond. However, we still permit client connection.
- *
- * TODO: We should have a default llm that tells the client
- * that the sessiond had a fatal error and thus the client could
- * take action to restart ltt-sessiond or inform someone.
- */
+ ret = process_client_msg(sock, &lsm);
+ if (ret < 0) {
+ /* Error detected but still accept command */
+ continue;
+/*
+ * send_unix_sock
+ *
+ * Send data on a unix socket using the liblttsessiondcomm API.
+ *
+ * Return lttcomm error code.
+ */
+static int send_unix_sock(int sock, void *buf, size_t len)
+{
+ /* Check valid length */
+ if (len <= 0) {
+ return -1;
+ }
+
+ return lttcomm_send_unix_sock(sock, buf, len);
+}
+
*
* Return size of the array.
*/
*
* Return size of the array.
*/
-static size_t ust_list_apps(pid_t *pids)
+static size_t ust_list_apps(pid_t **pids)
{
size_t size = 0;
struct ltt_traceable_app *iter = NULL;
{
size_t size = 0;
struct ltt_traceable_app *iter = NULL;
- cds_list_for_each_entry(iter, <t_traceable_app_list.head, list) {
- if (size >= MAX_APPS_PID) {
- break;
- }
+ if (traceable_app_count == 0) {
+ /* No dynamic allocation is done */
+ goto end;
+ }
+
+ p = malloc(sizeof(pid_t) * traceable_app_count);
- pids[size] = iter->pid;
+ /* TODO: Mutex needed to access this list */
+ cds_list_for_each_entry(iter, <t_traceable_app_list.head, list) {
+ p[size] = iter->pid;
+/*
+ * copy_common_data
+ *
+ * Copy common data between lttcomm_lttng_msg and lttcomm_session_msg
+ */
+static void copy_common_data(struct lttcomm_lttng_msg *llm, struct lttcomm_session_msg *lsm)
+{
+ llm->cmd_type = lsm->cmd_type;
+ llm->pid = lsm->pid;
+ if (!uuid_is_null(lsm->session_id)) {
+ uuid_copy(llm->session_id, lsm->session_id);
+ }
+ strncpy(llm->trace_name, lsm->trace_name, sizeof(llm->trace_name));
+}
+
/*
* process_client_msg
*
* This takes the lttcomm_session_msg struct and process the command requested
/*
* process_client_msg
*
* This takes the lttcomm_session_msg struct and process the command requested
- * by the client. It then creates the reply by allocating a lttcomm_lttng_msg
- * and fill it with the necessary information.
+ * by the client. It then creates response(s) and send it back to the
+ * given socket (sock).
- * It's the caller responsability to free that structure when done with it.
- *
- * Return pointer to lttcomm_lttng_msg allocated struct.
+ * Return any error encountered or 0 for success.
-static struct lttcomm_lttng_msg *process_client_msg(struct lttcomm_session_msg *lsm)
+static int process_client_msg(int sock, struct lttcomm_session_msg *lsm)
- struct lttcomm_lttng_msg *llm;
-
- /* Allocate the reply message structure */
- llm = malloc(sizeof(struct lttcomm_lttng_msg));
- if (llm == NULL) {
- perror("malloc");
- goto end;
- }
+ int ret;
+ struct lttcomm_lttng_msg llm;
/* Copy common data to identify the response
* on the lttng client side.
*/
/* Copy common data to identify the response
* on the lttng client side.
*/
- llm->cmd_type = lsm->cmd_type;
- llm->pid = lsm->pid;
- if (!uuid_is_null(lsm->session_id)) {
- uuid_copy(llm->session_id, lsm->session_id);
- }
- strncpy(llm->trace_name, lsm->trace_name, sizeof(llm->trace_name));
+ copy_common_data(&llm, lsm);
- * In a our world, everything is OK... right?
+ * In our world, everything is OK... right? ;)
- llm->ret_code = LTTCOMM_OK;
+ llm.ret_code = LTTCOMM_OK;
/* Process by command type */
switch (lsm->cmd_type) {
case UST_LIST_APPS:
{
/* Process by command type */
switch (lsm->cmd_type) {
case UST_LIST_APPS:
{
- llm->u.list_apps.size = ust_list_apps(llm->u.list_apps.pids);
+ pid_t *pids;
+ llm.num_pckt = ust_list_apps(&pids);
+ if (llm.num_pckt == 0) {
+ ret = LTTCOMM_NO_APPS;
+ goto error;
+ }
+
+ /* Send all packets */
+ while (llm.num_pckt != 0) {
+ llm.u.list_apps.pid = pids[traceable_app_count - llm.num_pckt];
+ ret = send_unix_sock(sock, (void*) &llm, sizeof(llm));
+ if (ret < 0) {
+ goto send_error;
+ }
+ llm.num_pckt--;
+ }
+ /* Allocated array by ust_list_apps() */
+ free(pids);
+
- llm->ret_code = LTTCOMM_UND;
+ return 0;
+
+send_error:
+ return ret;
+
+error:
+ /* Notify client of error */
+ llm.ret_code = ret;
+ send_unix_sock(sock, (void*) &llm, sizeof(llm));
+
+ return -1;
+ /* Allocated by lttng_ust_list_apps() */
+ free(pids);
+