X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=74f448a88d8c65f223b60b423eb177c322618db4;hp=91fba2643fc2ae94acf79850fd0e9aa589cfbf90;hb=a78af745624dfc8bfe90748a1730fecbb4677a17;hpb=c617c0c651432f9d5ae7adf4c5c1a5fd92ad828e diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 91fba2643..74f448a88 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -72,6 +72,7 @@ const char default_global_apps_pipe[] = DEFAULT_GLOBAL_APPS_PIPE; const char *progname; const char *opt_tracing_group; +static const char *opt_pidfile; static int opt_sig_parent; static int opt_verbose_consumer; static int opt_daemon; @@ -221,12 +222,6 @@ enum consumerd_state { static enum consumerd_state ust_consumerd_state; static enum consumerd_state kernel_consumerd_state; -/* Used for the health monitoring of the session daemon. See health.h */ -struct health_state health_thread_cmd; -struct health_state health_thread_app_manage; -struct health_state health_thread_app_reg; -struct health_state health_thread_kernel; - /* * Socket timeout for receiving and sending in seconds. */ @@ -404,6 +399,17 @@ static void cleanup(void) /* First thing first, stop all threads */ utils_close_pipe(thread_quit_pipe); + /* + * If opt_pidfile is undefined, the default file will be wiped when + * removing the rundir. + */ + if (opt_pidfile) { + ret = remove(opt_pidfile); + if (ret < 0) { + PERROR("remove pidfile %s", opt_pidfile); + } + } + DBG("Removing %s directory", rundir); ret = asprintf(&cmd, "rm -rf %s", rundir); if (ret < 0) { @@ -626,7 +632,7 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd) struct lttng_ht_iter iter; struct consumer_socket *socket; - + rcu_read_lock(); cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter, socket, node.node) { /* Code flow error */ @@ -637,9 +643,11 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd) channel, ksess); pthread_mutex_unlock(socket->lock); if (ret < 0) { + rcu_read_unlock(); goto error; } } + rcu_read_unlock(); } goto error; } @@ -691,36 +699,42 @@ static void *thread_manage_kernel(void *data) DBG("[thread] Thread manage kernel started"); - if (testpoint(thread_manage_kernel)) { - goto error_testpoint; - } + health_register(HEALTH_TYPE_KERNEL); - health_code_update(&health_thread_kernel); + /* + * This first step of the while is to clean this structure which could free + * non NULL pointers so zero it before the loop. + */ + memset(&events, 0, sizeof(events)); - ret = create_thread_poll_set(&events, 2); - if (ret < 0) { - goto error_poll_create; + if (testpoint(thread_manage_kernel)) { + goto error_testpoint; } - ret = lttng_poll_add(&events, kernel_poll_pipe[0], LPOLLIN); - if (ret < 0) { - goto error; - } + health_code_update(); if (testpoint(thread_manage_kernel_before_loop)) { - goto error; + goto error_testpoint; } while (1) { - health_code_update(&health_thread_kernel); + health_code_update(); 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; + /* Clean events object. We are about to populate it again. */ + lttng_poll_clean(&events); + + ret = create_thread_poll_set(&events, 2); + if (ret < 0) { + goto error_poll_create; + } + + ret = lttng_poll_add(&events, kernel_poll_pipe[0], LPOLLIN); + if (ret < 0) { + goto error; + } + /* This will add the available kernel channel if any. */ ret = update_kernel_poll(&events); if (ret < 0) { goto error; @@ -728,13 +742,13 @@ static void *thread_manage_kernel(void *data) update_poll_flag = 0; } - DBG("Thread kernel polling on %d fds", events.nb_fd); + DBG("Thread kernel polling on %d fds", LTTNG_POLL_GETNB(&events)); /* Poll infinite value of time */ restart: - health_poll_update(&health_thread_kernel); + health_poll_entry(); ret = lttng_poll_wait(&events, -1); - health_poll_update(&health_thread_kernel); + health_poll_exit(); if (ret < 0) { /* * Restart interrupted system call. @@ -757,7 +771,7 @@ static void *thread_manage_kernel(void *data) revents = LTTNG_POLL_GETEV(&events, i); pollfd = LTTNG_POLL_GETFD(&events, i); - health_code_update(&health_thread_kernel); + health_code_update(); /* Thread quit pipe has been closed. Killing thread. */ ret = check_thread_quit_pipe(pollfd, revents); @@ -768,7 +782,13 @@ static void *thread_manage_kernel(void *data) /* Check for data on kernel pipe */ if (pollfd == kernel_poll_pipe[0] && (revents & LPOLLIN)) { - ret = read(kernel_poll_pipe[0], &tmp, 1); + do { + ret = read(kernel_poll_pipe[0], &tmp, 1); + } while (ret < 0 && errno == EINTR); + /* + * Ret value is useless here, if this pipe gets any actions an + * update is required anyway. + */ update_poll_flag = 1; continue; } else { @@ -799,12 +819,12 @@ error_testpoint: utils_close_pipe(kernel_poll_pipe); kernel_poll_pipe[0] = kernel_poll_pipe[1] = -1; if (err) { - health_error(&health_thread_kernel); + health_error(); ERR("Health error occurred in %s", __func__); WARN("Kernel thread died unexpectedly. " "Kernel tracing can continue but CPU hotplug is disabled."); } - health_exit(&health_thread_kernel); + health_unregister(); DBG("Kernel thread dying"); return NULL; } @@ -845,6 +865,8 @@ static void *thread_manage_consumer(void *data) DBG("[thread] Manage consumer started"); + health_register(HEALTH_TYPE_CONSUMER); + /* * Since the consumer thread can be spawned at any moment in time, we init * the health to a poll status (1, which is a valid health over time). @@ -862,7 +884,7 @@ static void *thread_manage_consumer(void *data) * In a nutshell, the following poll update to the health state brings back * the state to an even value meaning a code path. */ - health_poll_update(&consumer_data->health); + health_poll_update(); /* * Pass 2 as size here for the thread quit pipe and kconsumerd_err_sock. @@ -883,18 +905,18 @@ static void *thread_manage_consumer(void *data) goto error; } - health_code_update(&consumer_data->health); + health_code_update(); /* Inifinite blocking call, waiting for transmission */ restart: - health_poll_update(&consumer_data->health); + health_poll_entry(); if (testpoint(thread_manage_consumer)) { goto error; } ret = lttng_poll_wait(&events, -1); - health_poll_update(&consumer_data->health); + health_poll_exit(); if (ret < 0) { /* * Restart interrupted system call. @@ -912,7 +934,7 @@ restart: revents = LTTNG_POLL_GETEV(&events, i); pollfd = LTTNG_POLL_GETFD(&events, i); - health_code_update(&consumer_data->health); + health_code_update(); /* Thread quit pipe has been closed. Killing thread. */ ret = check_thread_quit_pipe(pollfd, revents); @@ -941,7 +963,7 @@ restart: */ (void) utils_set_fd_cloexec(sock); - health_code_update(&consumer_data->health); + health_code_update(); DBG2("Receiving code from consumer err_sock"); @@ -952,7 +974,7 @@ restart: goto error; } - health_code_update(&consumer_data->health); + health_code_update(); if (code == LTTCOMM_CONSUMERD_COMMAND_SOCK_READY) { consumer_data->cmd_sock = @@ -982,13 +1004,13 @@ restart: goto error; } - health_code_update(&consumer_data->health); + health_code_update(); /* Inifinite blocking call, waiting for transmission */ restart_poll: - health_poll_update(&consumer_data->health); + health_poll_entry(); ret = lttng_poll_wait(&events, -1); - health_poll_update(&consumer_data->health); + health_poll_exit(); if (ret < 0) { /* * Restart interrupted system call. @@ -1006,7 +1028,7 @@ restart_poll: revents = LTTNG_POLL_GETEV(&events, i); pollfd = LTTNG_POLL_GETFD(&events, i); - health_code_update(&consumer_data->health); + health_code_update(); /* Thread quit pipe has been closed. Killing thread. */ ret = check_thread_quit_pipe(pollfd, revents); @@ -1024,7 +1046,7 @@ restart_poll: } } - health_code_update(&consumer_data->health); + health_code_update(); /* Wait for any kconsumerd error */ ret = lttcomm_recv_unix_sock(sock, &code, @@ -1075,10 +1097,10 @@ error: lttng_poll_clean(&events); error_poll: if (err) { - health_error(&consumer_data->health); + health_error(); ERR("Health error occurred in %s", __func__); } - health_exit(&consumer_data->health); + health_unregister(); DBG("consumer thread cleanup completed"); return NULL; @@ -1099,11 +1121,13 @@ static void *thread_manage_apps(void *data) rcu_register_thread(); rcu_thread_online(); + health_register(HEALTH_TYPE_APP_MANAGE); + if (testpoint(thread_manage_apps)) { goto error_testpoint; } - health_code_update(&health_thread_app_manage); + health_code_update(); ret = create_thread_poll_set(&events, 2); if (ret < 0) { @@ -1119,16 +1143,16 @@ static void *thread_manage_apps(void *data) goto error; } - health_code_update(&health_thread_app_manage); + health_code_update(); while (1) { - DBG("Apps thread polling on %d fds", events.nb_fd); + DBG("Apps thread polling on %d fds", LTTNG_POLL_GETNB(&events)); /* Inifinite blocking call, waiting for transmission */ restart: - health_poll_update(&health_thread_app_manage); + health_poll_entry(); ret = lttng_poll_wait(&events, -1); - health_poll_update(&health_thread_app_manage); + health_poll_exit(); if (ret < 0) { /* * Restart interrupted system call. @@ -1146,7 +1170,7 @@ static void *thread_manage_apps(void *data) revents = LTTNG_POLL_GETEV(&events, i); pollfd = LTTNG_POLL_GETFD(&events, i); - health_code_update(&health_thread_app_manage); + health_code_update(); /* Thread quit pipe has been closed. Killing thread. */ ret = check_thread_quit_pipe(pollfd, revents); @@ -1162,13 +1186,15 @@ static void *thread_manage_apps(void *data) goto error; } else if (revents & LPOLLIN) { /* Empty pipe */ - ret = read(apps_cmd_pipe[0], &ust_cmd, sizeof(ust_cmd)); + do { + ret = read(apps_cmd_pipe[0], &ust_cmd, sizeof(ust_cmd)); + } while (ret < 0 && errno == EINTR); if (ret < 0 || ret < sizeof(ust_cmd)) { PERROR("read apps cmd pipe"); goto error; } - health_code_update(&health_thread_app_manage); + health_code_update(); /* Register applicaton to the session daemon */ ret = ust_app_register(&ust_cmd.reg_msg, @@ -1179,7 +1205,7 @@ static void *thread_manage_apps(void *data) break; } - health_code_update(&health_thread_app_manage); + health_code_update(); /* * Validate UST version compatibility. @@ -1193,7 +1219,7 @@ static void *thread_manage_apps(void *data) update_ust_app(ust_cmd.sock); } - health_code_update(&health_thread_app_manage); + health_code_update(); ret = ust_app_register_done(ust_cmd.sock); if (ret < 0) { @@ -1224,7 +1250,7 @@ static void *thread_manage_apps(void *data) ust_cmd.sock); } - health_code_update(&health_thread_app_manage); + health_code_update(); break; } @@ -1246,7 +1272,7 @@ static void *thread_manage_apps(void *data) } } - health_code_update(&health_thread_app_manage); + health_code_update(); } } @@ -1265,10 +1291,10 @@ error_testpoint: */ if (err) { - health_error(&health_thread_app_manage); + health_error(); ERR("Health error occurred in %s", __func__); } - health_exit(&health_thread_app_manage); + health_unregister(); DBG("Application communication apps thread cleanup complete"); rcu_thread_offline(); rcu_unregister_thread(); @@ -1314,9 +1340,11 @@ static void *thread_dispatch_ust_registration(void *data) * at some point in time or wait to the end of the world :) */ if (apps_cmd_pipe[1] >= 0) { - ret = write(apps_cmd_pipe[1], ust_cmd, - sizeof(struct ust_command)); - if (ret < 0) { + do { + ret = write(apps_cmd_pipe[1], ust_cmd, + sizeof(struct ust_command)); + } while (ret < 0 && errno == EINTR); + if (ret < 0 || ret != sizeof(struct ust_command)) { PERROR("write apps cmd pipe"); if (errno == EBADF) { /* @@ -1363,6 +1391,8 @@ static void *thread_registration_apps(void *data) DBG("[thread] Manage application registration started"); + health_register(HEALTH_TYPE_APP_REG); + if (testpoint(thread_registration_apps)) { goto error_testpoint; } @@ -1400,9 +1430,9 @@ static void *thread_registration_apps(void *data) /* Inifinite blocking call, waiting for transmission */ restart: - health_poll_update(&health_thread_app_reg); + health_poll_entry(); ret = lttng_poll_wait(&events, -1); - health_poll_update(&health_thread_app_reg); + health_poll_exit(); if (ret < 0) { /* * Restart interrupted system call. @@ -1416,7 +1446,7 @@ static void *thread_registration_apps(void *data) nb_fd = ret; for (i = 0; i < nb_fd; i++) { - health_code_update(&health_thread_app_reg); + health_code_update(); /* Fetch once the poll data */ revents = LTTNG_POLL_GETEV(&events, i); @@ -1468,7 +1498,7 @@ static void *thread_registration_apps(void *data) sock = -1; continue; } - health_code_update(&health_thread_app_reg); + health_code_update(); ret = lttcomm_recv_unix_sock(sock, &ust_cmd->reg_msg, sizeof(struct ust_register_msg)); if (ret < 0 || ret < sizeof(struct ust_register_msg)) { @@ -1486,7 +1516,7 @@ static void *thread_registration_apps(void *data) sock = -1; continue; } - health_code_update(&health_thread_app_reg); + health_code_update(); ust_cmd->sock = sock; sock = -1; @@ -1517,7 +1547,7 @@ static void *thread_registration_apps(void *data) exit: error: if (err) { - health_error(&health_thread_app_reg); + health_error(); ERR("Health error occurred in %s", __func__); } @@ -1545,7 +1575,7 @@ error_listen: error_create_poll: error_testpoint: DBG("UST Registration thread cleanup complete"); - health_exit(&health_thread_app_reg); + health_unregister(); return NULL; } @@ -1920,9 +1950,7 @@ static int check_consumer_health(void) { int ret; - ret = health_check_state(&kconsumer_data.health) && - health_check_state(&ustconsumer32_data.health) && - health_check_state(&ustconsumer64_data.health); + ret = health_check_state(HEALTH_TYPE_CONSUMER); DBG3("Health consumer check %d", ret); @@ -2076,7 +2104,7 @@ static int create_ust_session(struct ltt_session *session, DBG("Creating UST session"); - lus = trace_ust_create_session(session->path, session->id, domain); + lus = trace_ust_create_session(session->path, session->id); if (lus == NULL) { ret = LTTNG_ERR_UST_SESS_FAIL; goto error; @@ -3040,26 +3068,26 @@ restart: switch (msg.component) { case LTTNG_HEALTH_CMD: - reply.ret_code = health_check_state(&health_thread_cmd); + reply.ret_code = health_check_state(HEALTH_TYPE_CMD); break; case LTTNG_HEALTH_APP_MANAGE: - reply.ret_code = health_check_state(&health_thread_app_manage); + reply.ret_code = health_check_state(HEALTH_TYPE_APP_MANAGE); break; case LTTNG_HEALTH_APP_REG: - reply.ret_code = health_check_state(&health_thread_app_reg); + reply.ret_code = health_check_state(HEALTH_TYPE_APP_REG); break; case LTTNG_HEALTH_KERNEL: - reply.ret_code = health_check_state(&health_thread_kernel); + reply.ret_code = health_check_state(HEALTH_TYPE_KERNEL); break; case LTTNG_HEALTH_CONSUMER: reply.ret_code = check_consumer_health(); break; case LTTNG_HEALTH_ALL: reply.ret_code = - health_check_state(&health_thread_app_manage) && - health_check_state(&health_thread_app_reg) && - health_check_state(&health_thread_cmd) && - health_check_state(&health_thread_kernel) && + health_check_state(HEALTH_TYPE_APP_MANAGE) && + health_check_state(HEALTH_TYPE_APP_REG) && + health_check_state(HEALTH_TYPE_CMD) && + health_check_state(HEALTH_TYPE_KERNEL) && check_consumer_health(); break; default: @@ -3134,11 +3162,13 @@ static void *thread_manage_clients(void *data) rcu_register_thread(); + health_register(HEALTH_TYPE_CMD); + if (testpoint(thread_manage_clients)) { goto error_testpoint; } - health_code_update(&health_thread_cmd); + health_code_update(); ret = lttcomm_listen_unix_sock(client_sock); if (ret < 0) { @@ -3171,16 +3201,16 @@ static void *thread_manage_clients(void *data) goto error; } - health_code_update(&health_thread_cmd); + health_code_update(); while (1) { DBG("Accepting client command ..."); /* Inifinite blocking call, waiting for transmission */ restart: - health_poll_update(&health_thread_cmd); + health_poll_entry(); ret = lttng_poll_wait(&events, -1); - health_poll_update(&health_thread_cmd); + health_poll_exit(); if (ret < 0) { /* * Restart interrupted system call. @@ -3198,7 +3228,7 @@ static void *thread_manage_clients(void *data) revents = LTTNG_POLL_GETEV(&events, i); pollfd = LTTNG_POLL_GETFD(&events, i); - health_code_update(&health_thread_cmd); + health_code_update(); /* Thread quit pipe has been closed. Killing thread. */ ret = check_thread_quit_pipe(pollfd, revents); @@ -3218,7 +3248,7 @@ static void *thread_manage_clients(void *data) DBG("Wait for client response"); - health_code_update(&health_thread_cmd); + health_code_update(); sock = lttcomm_accept_unix_sock(client_sock); if (sock < 0) { @@ -3254,7 +3284,7 @@ static void *thread_manage_clients(void *data) cmd_ctx->llm = NULL; cmd_ctx->session = NULL; - health_code_update(&health_thread_cmd); + health_code_update(); /* * Data is received from the lttng client. The struct @@ -3275,7 +3305,7 @@ static void *thread_manage_clients(void *data) continue; } - health_code_update(&health_thread_cmd); + health_code_update(); // TODO: Validate cmd_ctx including sanity check for // security purpose. @@ -3308,7 +3338,7 @@ static void *thread_manage_clients(void *data) continue; } - health_code_update(&health_thread_cmd); + health_code_update(); DBG("Sending response (size: %d, retcode: %s)", cmd_ctx->lttng_msg_size, @@ -3327,7 +3357,7 @@ static void *thread_manage_clients(void *data) clean_command_ctx(&cmd_ctx); - health_code_update(&health_thread_cmd); + health_code_update(); } exit: @@ -3354,11 +3384,11 @@ error_testpoint: } if (err) { - health_error(&health_thread_cmd); + health_error(); ERR("Health error occurred in %s", __func__); } - health_exit(&health_thread_cmd); + health_unregister(); DBG("Client thread dying"); @@ -3392,6 +3422,7 @@ static void usage(void) 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, " -p, --pidfile FILE Write a pid to FILE name overriding the default value.\n"); fprintf(stderr, " --verbose-consumer Verbose mode for consumer. Activate DBG() macro.\n"); fprintf(stderr, " --no-kernel Disable kernel tracer\n"); } @@ -3425,12 +3456,13 @@ static int parse_args(int argc, char **argv) { "verbose", 0, 0, 'v' }, { "verbose-consumer", 0, 0, 'Z' }, { "no-kernel", 0, 0, 'N' }, + { "pidfile", 1, 0, 'p' }, { NULL, 0, 0, 0 } }; while (1) { int option_index = 0; - c = getopt_long(argc, argv, "dhqvVSN" "a:c:g:s:C:E:D:F:Z:u:t", + c = getopt_long(argc, argv, "dhqvVSN" "a:c:g:s:C:E:D:F:Z:u:t:p:", long_options, &option_index); if (c == -1) { break; @@ -3507,6 +3539,9 @@ static int parse_args(int argc, char **argv) case 'T': consumerd64_libdir = optarg; break; + case 'p': + opt_pidfile = optarg; + break; default: /* Unknown option or other error. * Error is printed by getopt, just return */ @@ -3833,6 +3868,38 @@ static void set_ulimit(void) } } +/* + * Write pidfile using the rundir and opt_pidfile. + */ +static void write_pidfile(void) +{ + int ret; + char pidfile_path[PATH_MAX]; + + assert(rundir); + + if (opt_pidfile) { + strncpy(pidfile_path, opt_pidfile, sizeof(pidfile_path)); + } else { + /* Build pidfile path from rundir and opt_pidfile. */ + ret = snprintf(pidfile_path, sizeof(pidfile_path), "%s/" + DEFAULT_LTTNG_SESSIOND_PIDFILE, rundir); + if (ret < 0) { + PERROR("snprintf pidfile path"); + goto error; + } + } + + /* + * Create pid file in rundir. Return value is of no importance. The + * execution will continue even though we are not able to write the file. + */ + (void) utils_create_pid_file(getpid(), pidfile_path); + +error: + return; +} + /* * main */ @@ -4102,26 +4169,6 @@ int main(int argc, char **argv) cmd_init(); - /* Init all health thread counters. */ - health_init(&health_thread_cmd); - health_init(&health_thread_kernel); - health_init(&health_thread_app_manage); - health_init(&health_thread_app_reg); - - /* - * Init health counters of the consumer thread. We do a quick hack here to - * the state of the consumer health is fine even if the thread is not - * started. Once the thread starts, the health state is updated with a poll - * value to set a health code path. This is simply to ease our life and has - * no cost what so ever. - */ - health_init(&kconsumer_data.health); - health_poll_update(&kconsumer_data.health); - health_init(&ustconsumer32_data.health); - health_poll_update(&ustconsumer32_data.health); - health_init(&ustconsumer64_data.health); - health_poll_update(&ustconsumer64_data.health); - /* Check for the application socket timeout env variable. */ env_app_timeout = getenv(DEFAULT_APP_SOCKET_TIMEOUT_ENV); if (env_app_timeout) { @@ -4130,6 +4177,8 @@ int main(int argc, char **argv) app_socket_timeout = DEFAULT_APP_SOCKET_RW_TIMEOUT; } + write_pidfile(); + /* Create thread to manage the client socket */ ret = pthread_create(&health_thread, NULL, thread_manage_health, (void *) NULL);