X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-relayd%2Fmain.c;h=d8105e4058128bdc9a902bb8051fc991971f2b90;hp=506bbc6fb87249fe933cab9be2dfadb7f0a11d1c;hb=601262d65a9ccd90198558639ef2a73cda4230e1;hpb=87e45c13276c771ae797eb84fa1e42c36cb8cde2 diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c index 506bbc6fb..d8105e405 100644 --- a/src/bin/lttng-relayd/main.c +++ b/src/bin/lttng-relayd/main.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -60,10 +61,21 @@ #include "lttng-relayd.h" #include "live.h" #include "health-relayd.h" +#include "testpoint.h" /* command line options */ char *opt_output_path; -static int opt_daemon; +static int opt_daemon, opt_background; + +/* + * We need to wait for listener and live listener threads, as well as + * health check thread, before being ready to signal readiness. + */ +#define NR_LTTNG_RELAY_READY 3 +static int lttng_relay_ready = NR_LTTNG_RELAY_READY; +static int recv_child_signal; /* Set to 1 when a SIGUSR1 signal is received. */ +static pid_t child_ppid; /* Internal parent PID use with daemonize. */ + static struct lttng_uri *control_uri; static struct lttng_uri *data_uri; static struct lttng_uri *live_uri; @@ -79,7 +91,7 @@ const char * const config_section_name = "relayd"; * Quit pipe for all threads. This permits a single cancellation point * for all threads when receiving an event on the pipe. */ -static int thread_quit_pipe[2] = { -1, -1 }; +int thread_quit_pipe[2] = { -1, -1 }; /* * This pipe is used to inform the worker thread that a command is queued and @@ -131,6 +143,7 @@ static struct option long_options[] = { { "data-port", 1, 0, 'D', }, { "live-port", 1, 0, 'L', }, { "daemonize", 0, 0, 'd', }, + { "background", 0, 0, 'b', }, { "group", 1, 0, 'g', }, { "help", 0, 0, 'h', }, { "output", 1, 0, 'o', }, @@ -150,6 +163,7 @@ void usage(void) fprintf(stderr, "Usage: %s OPTIONS\n\nOptions:\n", progname); fprintf(stderr, " -h, --help Display this usage.\n"); fprintf(stderr, " -d, --daemonize Start as a daemon.\n"); + fprintf(stderr, " -b, --background Start as a daemon, keeping console open.\n"); fprintf(stderr, " -C, --control-port URL Control port listening.\n"); fprintf(stderr, " -D, --data-port URL Data port listening.\n"); fprintf(stderr, " -L, --live-port URL Live view port listening.\n"); @@ -210,6 +224,9 @@ int set_option(int opt, const char *arg, const char *optname) case 'd': opt_daemon = 1; break; + case 'b': + opt_background = 1; + break; case 'g': tracing_group_name = strdup(arg); tracing_group_name_override = 1; @@ -504,6 +521,9 @@ void sighandler(int sig) DBG("SIGTERM caught"); stop_threads(); break; + case SIGUSR1: + CMM_STORE_SHARED(recv_child_signal, 1); + break; default: break; } @@ -543,11 +563,26 @@ int set_signal_handler(void) return ret; } - DBG("Signal handler set for SIGTERM, SIGPIPE and SIGINT"); + if ((ret = sigaction(SIGUSR1, &sa, NULL)) < 0) { + PERROR("sigaction"); + return ret; + } + + DBG("Signal handler set for SIGTERM, SIGUSR1, SIGPIPE and SIGINT"); return ret; } +void lttng_relay_notify_ready(void) +{ + /* Notify the parent of the fork() process that we are ready. */ + if (opt_daemon || opt_background) { + if (uatomic_sub_return(<tng_relay_ready, 1) == 0) { + kill(child_ppid, SIGUSR1); + } + } +} + /* * Init thread quit pipe. * @@ -582,7 +617,7 @@ int create_thread_poll_set(struct lttng_poll_event *events, int size) } /* Add quit pipe */ - ret = lttng_poll_add(events, thread_quit_pipe[0], LPOLLIN); + ret = lttng_poll_add(events, thread_quit_pipe[0], LPOLLIN | LPOLLERR); if (ret < 0) { goto error; } @@ -717,6 +752,12 @@ void *relay_thread_listener(void *data) goto error_poll_add; } + lttng_relay_notify_ready(); + + if (testpoint(relayd_thread_listener)) { + goto error_testpoint; + } + while (1) { health_code_update(); @@ -817,6 +858,7 @@ restart: exit: error: error_poll_add: +error_testpoint: lttng_poll_clean(&events); error_create_poll: if (data_sock->fd >= 0) { @@ -860,6 +902,10 @@ void *relay_thread_dispatcher(void *data) health_register(health_relayd, HEALTH_RELAYD_TYPE_DISPATCHER); + if (testpoint(relayd_thread_dispatcher)) { + goto error_testpoint; + } + health_code_update(); while (!CMM_LOAD_SHARED(dispatch_thread_exit)) { @@ -906,6 +952,7 @@ void *relay_thread_dispatcher(void *data) err = 0; error: +error_testpoint: if (err) { health_error(); ERR("Health error occurred in %s", __func__); @@ -1118,6 +1165,10 @@ int relay_create_session(struct lttcomm_relayd_hdr *recv_hdr, reply.session_id = htobe64(session->id); switch (cmd->minor) { + case 1: + case 2: + case 3: + break; case 4: /* LTTng sessiond 2.4 */ default: ret = cmd_create_session_2_4(cmd, session); @@ -1299,11 +1350,7 @@ int relay_add_stream(struct lttcomm_relayd_hdr *recv_hdr, * stream message is received, this list is emptied and streams are set * with the viewer ready flag. */ - if (stream->metadata_flag) { - stream->viewer_ready = 1; - } else { - queue_stream_handle(stream->stream_handle, cmd); - } + queue_stream_handle(stream->stream_handle, cmd); lttng_ht_node_init_ulong(&stream->stream_n, (unsigned long) stream->stream_handle); @@ -2524,6 +2571,10 @@ void *relay_thread_worker(void *data) health_register(health_relayd, HEALTH_RELAYD_TYPE_WORKER); + if (testpoint(relayd_thread_worker)) { + goto error_testpoint; + } + health_code_update(); /* table of connections indexed on socket */ @@ -2785,6 +2836,7 @@ relay_connections_ht_error: } DBG("Worker thread cleanup complete"); free(data_buffer); +error_testpoint: if (err) { health_error(); ERR("Health error occurred in %s", __func__); @@ -2817,11 +2869,6 @@ int main(int argc, char **argv) void *status; struct relay_local_data *relay_ctx; - /* Create thread quit pipe */ - if ((ret = init_thread_quit_pipe()) < 0) { - goto error; - } - /* Parse arguments */ progname = argv[0]; if ((ret = set_options(argc, argv)) < 0) { @@ -2847,12 +2894,28 @@ int main(int argc, char **argv) } /* Daemonize */ - if (opt_daemon) { - ret = daemon(0, 0); + if (opt_daemon || opt_background) { + int i; + + ret = lttng_daemonize(&child_ppid, &recv_child_signal, + !opt_background); if (ret < 0) { - PERROR("daemon"); goto exit; } + + /* + * We are in the child. Make sure all other file + * descriptors are closed, in case we are called with + * more opened file descriptors than the standard ones. + */ + for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) { + (void) close(i); + } + } + + /* Create thread quit pipe */ + if ((ret = init_thread_quit_pipe()) < 0) { + goto error; } /* We need those values for the file/dir creation. */ @@ -2951,7 +3014,7 @@ int main(int argc, char **argv) goto exit_listener; } - ret = live_start_threads(live_uri, relay_ctx, thread_quit_pipe); + ret = live_start_threads(live_uri, relay_ctx); if (ret != 0) { ERR("Starting live viewer threads"); goto exit_live;