X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=dbd99cc637659e242c1012cd6717f20b4e0a36d4;hp=2983cbf8c1da67dbed1c2092db68b3631532cb24;hb=b2d6628742a005a7583d4d884643ca8658b25ba2;hpb=4e4714cb244d7ace4f4a462a3923066fd4760669 diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 2983cbf8c..dbd99cc63 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -17,7 +17,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE #define _LGPL_SOURCE #include #include @@ -38,7 +37,6 @@ #include #include #include -#include #include #include @@ -49,7 +47,7 @@ #include #include #include -#include +#include #include "lttng-sessiond.h" #include "buffer-registry.h" @@ -712,7 +710,6 @@ static void sessiond_cleanup(void) wait_consumer(&ustconsumer64_data); wait_consumer(&ustconsumer32_data); - DBG("Cleaning up all agent apps"); agent_app_ht_clean(); @@ -802,6 +799,8 @@ static void sessiond_cleanup_options(void) free(kmod_probes_list); free(kmod_extra_probes_list); + run_as_destroy_worker(); + /* */ DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm" "Matthew, BEET driven development works!%c[%dm", @@ -872,34 +871,57 @@ error: * right amount of memory and copying the original information from the lsm * structure. * - * Return total size of the buffer pointed by buf. + * Return 0 on success, negative value on error. */ -static int setup_lttng_msg(struct command_ctx *cmd_ctx, size_t size) +static int setup_lttng_msg(struct command_ctx *cmd_ctx, + const void *payload_buf, size_t payload_len, + const void *cmd_header_buf, size_t cmd_header_len) { - int ret, buf_size; + int ret = 0; + const size_t header_len = sizeof(struct lttcomm_lttng_msg); + const size_t cmd_header_offset = header_len; + const size_t payload_offset = cmd_header_offset + cmd_header_len; + const size_t total_msg_size = header_len + cmd_header_len + payload_len; - buf_size = size; + cmd_ctx->llm = zmalloc(total_msg_size); - cmd_ctx->llm = zmalloc(sizeof(struct lttcomm_lttng_msg) + buf_size); if (cmd_ctx->llm == NULL) { PERROR("zmalloc"); ret = -ENOMEM; - goto error; + goto end; } /* Copy common data */ cmd_ctx->llm->cmd_type = cmd_ctx->lsm->cmd_type; cmd_ctx->llm->pid = cmd_ctx->lsm->domain.attr.pid; + cmd_ctx->llm->cmd_header_size = cmd_header_len; + cmd_ctx->llm->data_size = payload_len; + cmd_ctx->lttng_msg_size = total_msg_size; - cmd_ctx->llm->data_size = size; - cmd_ctx->lttng_msg_size = sizeof(struct lttcomm_lttng_msg) + buf_size; + /* Copy command header */ + if (cmd_header_len) { + memcpy(((uint8_t *) cmd_ctx->llm) + cmd_header_offset, cmd_header_buf, + cmd_header_len); + } - return buf_size; + /* Copy payload */ + if (payload_len) { + memcpy(((uint8_t *) cmd_ctx->llm) + payload_offset, payload_buf, + payload_len); + } -error: +end: return ret; } +/* + * Version of setup_lttng_msg() without command header. + */ +static int setup_lttng_msg_no_cmd_header(struct command_ctx *cmd_ctx, + void *payload_buf, size_t payload_len) +{ + return setup_lttng_msg(cmd_ctx, payload_buf, payload_len, NULL, 0); +} /* * Update the kernel poll set of all channel fd available over all tracing * session. Add the wakeup pipe at the end of the set. @@ -1166,31 +1188,33 @@ static void *thread_manage_kernel(void *data) } /* Check for data on kernel pipe */ - if (pollfd == kernel_poll_pipe[0] && (revents & LPOLLIN)) { - (void) lttng_read(kernel_poll_pipe[0], - &tmp, 1); - /* - * Ret value is useless here, if this pipe gets any actions an - * update is required anyway. - */ - update_poll_flag = 1; - continue; - } else { - /* - * New CPU detected by the kernel. Adding kernel stream to - * kernel session and updating the kernel consumer - */ - if (revents & LPOLLIN) { + if (revents & LPOLLIN) { + if (pollfd == kernel_poll_pipe[0]) { + (void) lttng_read(kernel_poll_pipe[0], + &tmp, 1); + /* + * Ret value is useless here, if this pipe gets any actions an + * update is required anyway. + */ + update_poll_flag = 1; + continue; + } else { + /* + * New CPU detected by the kernel. Adding kernel stream to + * kernel session and updating the kernel consumer + */ ret = update_kernel_stream(&kconsumer_data, pollfd); if (ret < 0) { continue; } break; - /* - * TODO: We might want to handle the LPOLLERR | LPOLLHUP - * and unregister kernel stream at this point. - */ } + } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + update_poll_flag = 1; + continue; + } else { + ERR("Unexpected poll events %u for sock %d", revents, pollfd); + goto error; } } } @@ -1320,9 +1344,14 @@ restart: /* Event on the registration socket */ if (pollfd == consumer_data->err_sock) { - if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + if (revents & LPOLLIN) { + continue; + } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { ERR("consumer err socket poll error"); goto error; + } else { + ERR("Unexpected poll events %u for sock %d", revents, pollfd); + goto error; } } } @@ -1452,7 +1481,8 @@ restart_poll: if (pollfd == sock) { /* Event on the consumerd socket */ - if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP) + && !(revents & LPOLLIN)) { ERR("consumer err socket second poll error"); goto error; } @@ -1470,6 +1500,11 @@ restart_poll: goto exit; } else if (pollfd == consumer_data->metadata_fd) { + if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP) + && !(revents & LPOLLIN)) { + ERR("consumer err metadata socket second poll error"); + goto error; + } /* UST metadata requests */ ret = ust_consumer_metadata_request( &consumer_data->metadata_sock); @@ -1637,10 +1672,7 @@ static void *thread_manage_apps(void *data) /* Inspect the apps cmd pipe */ if (pollfd == apps_cmd_pipe[0]) { - if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { - ERR("Apps command pipe error"); - goto error; - } else if (revents & LPOLLIN) { + if (revents & LPOLLIN) { int sock; /* Empty pipe */ @@ -1653,9 +1685,8 @@ static void *thread_manage_apps(void *data) health_code_update(); /* - * We only monitor the error events of the socket. This - * thread does not handle any incoming data from UST - * (POLLIN). + * Since this is a command socket (write then read), + * we only monitor the error events of the socket. */ ret = lttng_poll_add(&events, sock, LPOLLERR | LPOLLHUP | LPOLLRDHUP); @@ -1664,6 +1695,12 @@ static void *thread_manage_apps(void *data) } DBG("Apps with sock %d added to poll set", sock); + } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + ERR("Apps command pipe error"); + goto error; + } else { + ERR("Unknown poll events %u for sock %d", revents, pollfd); + goto error; } } else { /* @@ -1679,6 +1716,9 @@ static void *thread_manage_apps(void *data) /* Socket closed on remote end. */ ust_app_unregister(pollfd); + } else { + ERR("Unexpected poll events %u for sock %d", revents, pollfd); + goto error; } } @@ -1826,6 +1866,9 @@ static void sanitize_wait_queue(struct ust_reg_wait_queue *wait_queue) */ wait_node = NULL; break; + } else { + ERR("Unexpected poll events %u for sock %d", revents, pollfd); + goto error; } } } @@ -2186,10 +2229,7 @@ static void *thread_registration_apps(void *data) /* Event on the registration socket */ if (pollfd == apps_sock) { - if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { - ERR("Register apps socket poll error"); - goto error; - } else if (revents & LPOLLIN) { + if (revents & LPOLLIN) { sock = lttcomm_accept_unix_sock(apps_sock); if (sock < 0) { goto error; @@ -2276,6 +2316,12 @@ static void *thread_registration_apps(void *data) * barrier with the exchange in cds_wfcq_enqueue. */ futex_nto1_wake(&ust_cmd_queue.futex); + } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + ERR("Register apps socket poll error"); + goto error; + } else { + ERR("Unexpected poll events %u for sock %d", revents, pollfd); + goto error; } } } @@ -2973,6 +3019,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, DBG("Processing client command %d", cmd_ctx->lsm->cmd_type); + assert(!rcu_read_ongoing()); + *sock_error = 0; switch (cmd_ctx->lsm->cmd_type) { @@ -3035,7 +3083,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, break; default: /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, NULL, 0); if (ret < 0) { /* This label does not try to unlock the session */ goto init_setup_error; @@ -3318,9 +3366,74 @@ skip_domain: switch (cmd_ctx->lsm->cmd_type) { case LTTNG_ADD_CONTEXT: { - ret = cmd_add_context(cmd_ctx->session, cmd_ctx->lsm->domain.type, + /* + * An LTTNG_ADD_CONTEXT command might have a supplementary + * payload if the context being added is an application context. + */ + if (cmd_ctx->lsm->u.context.ctx.ctx == + LTTNG_EVENT_CONTEXT_APP_CONTEXT) { + char *provider_name = NULL, *context_name = NULL; + size_t provider_name_len = + cmd_ctx->lsm->u.context.provider_name_len; + size_t context_name_len = + cmd_ctx->lsm->u.context.context_name_len; + + if (provider_name_len == 0 || context_name_len == 0) { + /* + * Application provider and context names MUST + * be provided. + */ + ret = -LTTNG_ERR_INVALID; + goto error; + } + + provider_name = zmalloc(provider_name_len + 1); + if (!provider_name) { + ret = -LTTNG_ERR_NOMEM; + goto error; + } + cmd_ctx->lsm->u.context.ctx.u.app_ctx.provider_name = + provider_name; + + context_name = zmalloc(context_name_len + 1); + if (!context_name) { + ret = -LTTNG_ERR_NOMEM; + goto error_add_context; + } + cmd_ctx->lsm->u.context.ctx.u.app_ctx.ctx_name = + context_name; + + ret = lttcomm_recv_unix_sock(sock, provider_name, + provider_name_len); + if (ret < 0) { + goto error_add_context; + } + + ret = lttcomm_recv_unix_sock(sock, context_name, + context_name_len); + if (ret < 0) { + goto error_add_context; + } + } + + /* + * cmd_add_context assumes ownership of the provider and context + * names. + */ + ret = cmd_add_context(cmd_ctx->session, + cmd_ctx->lsm->domain.type, cmd_ctx->lsm->u.context.channel_name, - &cmd_ctx->lsm->u.context.ctx, kernel_poll_pipe[1]); + &cmd_ctx->lsm->u.context.ctx, + kernel_poll_pipe[1]); + + cmd_ctx->lsm->u.context.ctx.u.app_ctx.provider_name = NULL; + cmd_ctx->lsm->u.context.ctx.u.app_ctx.ctx_name = NULL; +error_add_context: + free(cmd_ctx->lsm->u.context.ctx.u.app_ctx.provider_name); + free(cmd_ctx->lsm->u.context.ctx.u.app_ctx.ctx_name); + if (ret < 0) { + goto error; + } break; } case LTTNG_DISABLE_CHANNEL: @@ -3512,18 +3625,14 @@ skip_domain: * Setup lttng message with payload size set to the event list size in * bytes and then copy list into the llm payload. */ - ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_event) * nb_events); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, events, + sizeof(struct lttng_event) * nb_events); + free(events); + if (ret < 0) { - free(events); goto setup_error; } - /* Copy event list into message payload */ - memcpy(cmd_ctx->llm->payload, events, - sizeof(struct lttng_event) * nb_events); - - free(events); - ret = LTTNG_OK; break; } @@ -3546,19 +3655,14 @@ skip_domain: * Setup lttng message with payload size set to the event list size in * bytes and then copy list into the llm payload. */ - ret = setup_lttng_msg(cmd_ctx, + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, fields, sizeof(struct lttng_event_field) * nb_fields); + free(fields); + if (ret < 0) { - free(fields); goto setup_error; } - /* Copy event list into message payload */ - memcpy(cmd_ctx->llm->payload, fields, - sizeof(struct lttng_event_field) * nb_fields); - - free(fields); - ret = LTTNG_OK; break; } @@ -3578,18 +3682,14 @@ skip_domain: * Setup lttng message with payload size set to the event list size in * bytes and then copy list into the llm payload. */ - ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_event) * nb_events); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, events, + sizeof(struct lttng_event) * nb_events); + free(events); + if (ret < 0) { - free(events); goto setup_error; } - /* Copy event list into message payload */ - memcpy(cmd_ctx->llm->payload, events, - sizeof(struct lttng_event) * nb_events); - - free(events); - ret = LTTNG_OK; break; } @@ -3610,18 +3710,14 @@ skip_domain: * Setup lttng message with payload size set to the event list size in * bytes and then copy list into the llm payload. */ - ret = setup_lttng_msg(cmd_ctx, sizeof(int32_t) * nr_pids); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, pids, + sizeof(int32_t) * nr_pids); + free(pids); + if (ret < 0) { - free(pids); goto setup_error; } - /* Copy event list into message payload */ - memcpy(cmd_ctx->llm->payload, pids, - sizeof(int) * nr_pids); - - free(pids); - ret = LTTNG_OK; break; } @@ -3735,46 +3831,38 @@ skip_domain: goto error; } - ret = setup_lttng_msg(cmd_ctx, nb_dom * sizeof(struct lttng_domain)); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, domains, + nb_dom * sizeof(struct lttng_domain)); + free(domains); + if (ret < 0) { - free(domains); goto setup_error; } - /* Copy event list into message payload */ - memcpy(cmd_ctx->llm->payload, domains, - nb_dom * sizeof(struct lttng_domain)); - - free(domains); - ret = LTTNG_OK; break; } case LTTNG_LIST_CHANNELS: { - int nb_chan; + ssize_t payload_size; struct lttng_channel *channels = NULL; - nb_chan = cmd_list_channels(cmd_ctx->lsm->domain.type, + payload_size = cmd_list_channels(cmd_ctx->lsm->domain.type, cmd_ctx->session, &channels); - if (nb_chan < 0) { + if (payload_size < 0) { /* Return value is a negative lttng_error_code. */ - ret = -nb_chan; + ret = -payload_size; goto error; } - ret = setup_lttng_msg(cmd_ctx, nb_chan * sizeof(struct lttng_channel)); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, channels, + payload_size); + free(channels); + if (ret < 0) { - free(channels); goto setup_error; } - /* Copy event list into message payload */ - memcpy(cmd_ctx->llm->payload, channels, - nb_chan * sizeof(struct lttng_channel)); - - free(channels); - ret = LTTNG_OK; break; } @@ -3782,52 +3870,65 @@ skip_domain: { ssize_t nb_event; struct lttng_event *events = NULL; + struct lttcomm_event_command_header cmd_header; + size_t total_size; + + memset(&cmd_header, 0, sizeof(cmd_header)); + /* Extended infos are included at the end of events */ + nb_event = cmd_list_events(cmd_ctx->lsm->domain.type, + cmd_ctx->session, cmd_ctx->lsm->u.list.channel_name, + &events, &total_size); - nb_event = cmd_list_events(cmd_ctx->lsm->domain.type, cmd_ctx->session, - cmd_ctx->lsm->u.list.channel_name, &events); if (nb_event < 0) { /* Return value is a negative lttng_error_code. */ ret = -nb_event; goto error; } - ret = setup_lttng_msg(cmd_ctx, nb_event * sizeof(struct lttng_event)); + cmd_header.nb_events = nb_event; + ret = setup_lttng_msg(cmd_ctx, events, total_size, + &cmd_header, sizeof(cmd_header)); + free(events); + if (ret < 0) { - free(events); goto setup_error; } - /* Copy event list into message payload */ - memcpy(cmd_ctx->llm->payload, events, - nb_event * sizeof(struct lttng_event)); - - free(events); - ret = LTTNG_OK; break; } case LTTNG_LIST_SESSIONS: { unsigned int nr_sessions; + void *sessions_payload; + size_t payload_len; session_lock_list(); nr_sessions = lttng_sessions_count( LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds)); + payload_len = sizeof(struct lttng_session) * nr_sessions; + sessions_payload = zmalloc(payload_len); - ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) * nr_sessions); - if (ret < 0) { + if (!sessions_payload) { session_unlock_list(); + ret = -ENOMEM; goto setup_error; } - /* Filled the session array */ - cmd_list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload), + cmd_list_lttng_sessions(sessions_payload, LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds)); - session_unlock_list(); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, sessions_payload, + payload_len); + free(sessions_payload); + + if (ret < 0) { + goto setup_error; + } + ret = LTTNG_OK; break; } @@ -3857,14 +3958,10 @@ skip_domain: case LTTNG_DATA_PENDING: { int pending_ret; - - /* 1 byte to return whether or not data is pending */ - ret = setup_lttng_msg(cmd_ctx, 1); - if (ret < 0) { - goto setup_error; - } + uint8_t pending_ret_byte; pending_ret = cmd_data_pending(cmd_ctx->session); + /* * FIXME * @@ -3875,7 +3972,10 @@ skip_domain: * "unknown" error. */ if (pending_ret == 0 || pending_ret == 1) { - ret = LTTNG_OK; + /* + * ret will be set to LTTNG_OK at the end of + * this function. + */ } else if (pending_ret < 0) { ret = LTTNG_ERR_UNK; goto setup_error; @@ -3884,7 +3984,17 @@ skip_domain: goto setup_error; } - *cmd_ctx->llm->payload = (uint8_t) pending_ret; + pending_ret_byte = (uint8_t) pending_ret; + + /* 1 byte to return whether or not data is pending */ + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, + &pending_ret_byte, 1); + + if (ret < 0) { + goto setup_error; + } + + ret = LTTNG_OK; break; } case LTTNG_SNAPSHOT_ADD_OUTPUT: @@ -3897,13 +4007,13 @@ skip_domain: goto error; } - ret = setup_lttng_msg(cmd_ctx, sizeof(reply)); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, &reply, + sizeof(reply)); if (ret < 0) { goto setup_error; } /* Copy output list into message payload */ - memcpy(cmd_ctx->llm->payload, &reply, sizeof(reply)); ret = LTTNG_OK; break; } @@ -3924,20 +4034,15 @@ skip_domain: goto error; } - ret = setup_lttng_msg(cmd_ctx, + assert((nb_output > 0 && outputs) || nb_output == 0); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, outputs, nb_output * sizeof(struct lttng_snapshot_output)); + free(outputs); + if (ret < 0) { - free(outputs); goto setup_error; } - if (outputs) { - /* Copy output list into message payload */ - memcpy(cmd_ctx->llm->payload, outputs, - nb_output * sizeof(struct lttng_snapshot_output)); - free(outputs); - } - ret = LTTNG_OK; break; } @@ -4046,7 +4151,7 @@ skip_domain: error: if (cmd_ctx->llm == NULL) { DBG("Missing llm structure. Allocating one."); - if (setup_lttng_msg(cmd_ctx, 0) < 0) { + if (setup_lttng_msg_no_cmd_header(cmd_ctx, NULL, 0) < 0) { goto setup_error; } } @@ -4060,6 +4165,7 @@ setup_error: session_unlock_list(); } init_setup_error: + assert(!rcu_read_ongoing()); return ret; } @@ -4175,9 +4281,14 @@ restart: /* Event on the registration socket */ if (pollfd == sock) { - if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + if (revents & LPOLLIN) { + continue; + } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { ERR("Health socket poll error"); goto error; + } else { + ERR("Unexpected poll events %u for sock %d", revents, pollfd); + goto error; } } } @@ -4352,9 +4463,14 @@ static void *thread_manage_clients(void *data) /* Event on the registration socket */ if (pollfd == client_sock) { - if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + if (revents & LPOLLIN) { + continue; + } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { ERR("Client socket poll error"); goto error; + } else { + ERR("Unexpected poll events %u for sock %d", revents, pollfd); + goto error; } } } @@ -4865,7 +4981,7 @@ end: /* * config_entry_handler_cb used to handle options read from a config file. - * See config_entry_handler_cb comment in common/config/config.h for the + * See config_entry_handler_cb comment in common/config/session-config.h for the * return value conventions. */ static int config_entry_handler(const struct config_entry *entry, void *unused) @@ -5474,6 +5590,10 @@ int main(int argc, char **argv) } } + if (run_as_create_worker(argv[0]) < 0) { + goto exit_create_run_as_worker_cleanup; + } + /* * Starting from here, we can create threads. This needs to be after * lttng_daemonize due to RCU. @@ -6091,13 +6211,15 @@ exit_ht_cleanup_quit_pipe: health_app_destroy(health_sessiond); exit_health_sessiond_cleanup: +exit_create_run_as_worker_cleanup: exit_options: + /* Ensure all prior call_rcu are done. */ + rcu_barrier(); + sessiond_cleanup_options(); exit_set_signal_handler: - /* Ensure all prior call_rcu are done. */ - rcu_barrier(); if (!retval) { exit(EXIT_SUCCESS);