From e065084a507dd07b658b3d26c58b1ddd519e25a0 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Wed, 20 Apr 2011 15:33:23 -0400 Subject: [PATCH] Change client message processing 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 --- liblttngctl/liblttngctl.c | 60 +++++++-- liblttsessiondcomm/liblttsessiondcomm.c | 1 + liblttsessiondcomm/liblttsessiondcomm.h | 14 +- ltt-sessiond/ltt-sessiond.c | 165 ++++++++++++++++-------- lttng/lttng.c | 3 + 5 files changed, 165 insertions(+), 78 deletions(-) diff --git a/liblttngctl/liblttngctl.c b/liblttngctl/liblttngctl.c index 2b4b8febc..d8481496d 100644 --- a/liblttngctl/liblttngctl.c +++ b/liblttngctl/liblttngctl.c @@ -40,6 +40,7 @@ static struct lttcomm_session_msg lsm; /* 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); @@ -54,8 +55,7 @@ static int connected; /* * ask_sessiond * - * 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 @@ -65,29 +65,45 @@ static int ask_sessiond(void) int ret; if (!connected) { - ret = -ECONNREFUSED; - goto error; + ret = -ENOTCONN; + goto end; } 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) { - goto error; + goto end; } /* Check return code */ if (llm.ret_code != LTTCOMM_OK) { ret = -llm.ret_code; - goto error; + goto end; } - return 0; - -error: +end: return ret; } @@ -152,7 +168,9 @@ end: */ size_t lttng_ust_list_apps(pid_t **pids) { - int ret; + int ret, first = 0; + size_t size = 0; + pid_t *p = NULL; lsm.cmd_type = UST_LIST_APPS; @@ -161,9 +179,23 @@ size_t lttng_ust_list_apps(pid_t **pids) goto error; } - *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; + return size; error: return ret; diff --git a/liblttsessiondcomm/liblttsessiondcomm.c b/liblttsessiondcomm/liblttsessiondcomm.c index 581d5c419..d2d22bc5d 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.c +++ b/liblttsessiondcomm/liblttsessiondcomm.c @@ -38,6 +38,7 @@ static const char *lttcomm_readable_code[] = { [ 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", }; /* diff --git a/liblttsessiondcomm/liblttsessiondcomm.h b/liblttsessiondcomm/liblttsessiondcomm.h index 0e2c4f07f..84385ce71 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.h +++ b/liblttsessiondcomm/liblttsessiondcomm.h @@ -31,11 +31,6 @@ /* 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 */ @@ -78,6 +73,7 @@ enum lttcomm_return_code { 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 */ }; @@ -126,11 +122,15 @@ struct lttcomm_lttng_msg { 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 { - size_t size; - pid_t pids[MAX_APPS_PID]; + pid_t pid; } list_apps; } u; }; diff --git a/ltt-sessiond/ltt-sessiond.c b/ltt-sessiond/ltt-sessiond.c index 6877acccb..d846c89e5 100644 --- a/ltt-sessiond/ltt-sessiond.c +++ b/ltt-sessiond/ltt-sessiond.c @@ -50,11 +50,13 @@ static int set_socket_perms(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 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 *); @@ -77,13 +79,17 @@ static int client_socket; 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 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), }; @@ -136,12 +142,17 @@ static void *thread_manage_apps(void *data) lta->pid = reg_msg.pid; lta->uid = reg_msg.uid; cds_list_add(<a->list, <t_traceable_app_list.head); + traceable_app_count++; } 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--; + } break; } } @@ -168,7 +179,6 @@ static void *thread_manage_clients(void *data) { int sock, ret; struct lttcomm_session_msg lsm; - struct lttcomm_lttng_msg *llm; ret = lttcomm_listen_unix_sock(client_socket); if (ret < 0) { @@ -193,29 +203,14 @@ static void *thread_manage_clients(void *data) } /* 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; } } @@ -223,6 +218,23 @@ error: return NULL; } +/* + * 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); +} + /* * connect_app * @@ -378,75 +390,114 @@ error: * * 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; + pid_t *p; - 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; size++; } + *pids = p; + +end: return size; } +/* + * 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 - * 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. */ - 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); /* Default return code. - * 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: { - 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); + break; } default: + { /* Undefined command */ - llm->ret_code = LTTCOMM_UND; + ret = LTTCOMM_UND; break; + } } -end: - return llm; + 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; } /* diff --git a/lttng/lttng.c b/lttng/lttng.c index f390fddb2..6cc540922 100644 --- a/lttng/lttng.c +++ b/lttng/lttng.c @@ -105,6 +105,9 @@ static int process_opt_list_apps(void) fclose(fp); } + /* Allocated by lttng_ust_list_apps() */ + free(pids); + return 0; error: -- 2.34.1