relayd: clean-up: reduce the number of exit paths in main()
[lttng-tools.git] / src / bin / lttng-relayd / main.c
index 5e99befa7c5c775ef888a4166366abf44a9a3114..07e7a012245d5fa0d36fd919f40d00c380070be1 100644 (file)
@@ -34,6 +34,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/resource.h>
 #include <inttypes.h>
 #include <urcu/futex.h>
 #include <urcu/uatomic.h>
@@ -41,6 +42,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <strings.h>
+#include <ctype.h>
 
 #include <lttng/lttng.h>
 #include <common/common.h>
@@ -160,6 +162,9 @@ static uint64_t last_relay_stream_id;
  */
 static struct relay_conn_queue relay_conn_queue;
 
+/* Cap of file desriptors to be in simultaneous use by the relay daemon. */
+static unsigned int lttng_opt_fd_cap;
+
 /* Global relay stream hash table. */
 struct lttng_ht *relay_streams_ht;
 
@@ -181,6 +186,7 @@ static struct option long_options[] = {
        { "daemonize", 0, 0, 'd', },
        { "background", 0, 0, 'b', },
        { "group", 1, 0, 'g', },
+       { "fd-cap", 1, 0, '\0', },
        { "help", 0, 0, 'h', },
        { "output", 1, 0, 'o', },
        { "verbose", 0, 0, 'v', },
@@ -224,9 +230,34 @@ static int set_option(int opt, const char *arg, const char *optname)
 
        switch (opt) {
        case 0:
-               fprintf(stderr, "option %s", optname);
-               if (arg) {
-                       fprintf(stderr, " with arg %s\n", arg);
+               if (!strcmp(optname, "fd-cap")) {
+                       unsigned long v;
+
+                       errno = 0;
+                       v = strtoul(arg, NULL, 0);
+                       if (errno != 0 || !isdigit(arg[0])) {
+                               ERR("Wrong value in --fd-cap parameter: %s",
+                                               arg);
+                               ret = -1;
+                               goto end;
+                       }
+                       if (v < DEFAULT_RELAYD_MINIMAL_FD_CAP) {
+                               ERR("File descriptor cap must be set to at least %d",
+                                               DEFAULT_RELAYD_MINIMAL_FD_CAP);
+                       }
+                       if (v >= UINT_MAX) {
+                               ERR("File descriptor cap overflow in --fd-cap parameter: %s",
+                                               arg);
+                               ret = -1;
+                               goto end;
+                       }
+                       lttng_opt_fd_cap = (unsigned int) v;
+                       DBG3("File descriptor cap set to %u", lttng_opt_fd_cap);
+               } else {
+                       fprintf(stderr, "unknown option %s", optname);
+                       if (arg) {
+                               fprintf(stderr, " with arg %s\n", arg);
+                       }
                }
                break;
        case 'C':
@@ -563,6 +594,18 @@ static int set_options(int argc, char **argv)
                        goto exit;
                }
        }
+       if (lttng_opt_fd_cap == 0) {
+               int ret;
+               struct rlimit rlimit;
+
+               ret = getrlimit(RLIMIT_NOFILE, &rlimit);
+               if (ret) {
+                       PERROR("Failed to get file descriptor limit");
+                       retval = -1;
+               }
+
+               lttng_opt_fd_cap = rlimit.rlim_cur;
+       }
 
        if (opt_group_output_by == RELAYD_GROUP_OUTPUT_BY_UNKNOWN) {
                opt_group_output_by = RELAYD_GROUP_OUTPUT_BY_HOST;
@@ -616,9 +659,18 @@ static void relayd_cleanup(void)
        free(opt_output_path);
        free(opt_working_directory);
 
+       if (health_relayd) {
+               health_app_destroy(health_relayd);
+       }
        /* Close thread quit pipes */
+       utils_close_pipe(health_quit_pipe);
        utils_close_pipe(thread_quit_pipe);
 
+       if (sessiond_trace_chunk_registry) {
+               sessiond_trace_chunk_registry_destroy(
+                               sessiond_trace_chunk_registry);
+       }
+
        uri_free(control_uri);
        uri_free(data_uri);
        /* Live URI is freed in the live thread. */
@@ -2699,6 +2751,20 @@ static int relay_close_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
        }
 
        pthread_mutex_lock(&session->lock);
+       if (close_command.is_set &&
+                       close_command.value == LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE) {
+               /*
+                * Clear command. It is a protocol error to ask for a
+                * clear on a relay which does not allow it. Querying
+                * the configuration allows figuring out whether
+                * clearing is allowed before doing the clear.
+                */
+               if (!opt_allow_clear) {
+                       ret = -1;
+                       reply_code = LTTNG_ERR_INVALID_PROTOCOL;
+                       goto end_unlock_session;
+               }
+       }
        if (session->pending_closure_trace_chunk &&
                        session->pending_closure_trace_chunk != chunk) {
                ERR("Trace chunk close command for session \"%s\" does not target the trace chunk pending closure",
@@ -4002,7 +4068,7 @@ int main(int argc, char **argv)
        if (!sessiond_trace_chunk_registry) {
                ERR("Failed to initialize session daemon trace chunk registry");
                retval = -1;
-               goto exit_sessiond_trace_chunk_registry;
+               goto exit_options;
        }
 
        /* Initialize thread health monitoring */
@@ -4010,19 +4076,19 @@ int main(int argc, char **argv)
        if (!health_relayd) {
                PERROR("health_app_create error");
                retval = -1;
-               goto exit_health_app_create;
+               goto exit_options;
        }
 
        /* Create thread quit pipe */
        if (init_thread_quit_pipe()) {
                retval = -1;
-               goto exit_init_data;
+               goto exit_options;
        }
 
        /* Setup the thread apps communication pipe. */
        if (create_relay_conn_pipe()) {
                retval = -1;
-               goto exit_init_data;
+               goto exit_options;
        }
 
        /* Init relay command queue. */
@@ -4036,27 +4102,27 @@ int main(int argc, char **argv)
        sessions_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
        if (!sessions_ht) {
                retval = -1;
-               goto exit_init_data;
+               goto exit_options;
        }
 
        /* tables of streams indexed by stream ID */
        relay_streams_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
        if (!relay_streams_ht) {
                retval = -1;
-               goto exit_init_data;
+               goto exit_options;
        }
 
        /* tables of streams indexed by stream ID */
        viewer_streams_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
        if (!viewer_streams_ht) {
                retval = -1;
-               goto exit_init_data;
+               goto exit_options;
        }
 
        ret = utils_create_pipe(health_quit_pipe);
        if (ret) {
                retval = -1;
-               goto exit_health_quit_pipe;
+               goto exit_options;
        }
 
        /* Create thread to manage the client socket */
@@ -4066,7 +4132,7 @@ int main(int argc, char **argv)
                errno = ret;
                PERROR("pthread_create health");
                retval = -1;
-               goto exit_health_thread;
+               goto exit_options;
        }
 
        /* Setup the dispatcher thread */
@@ -4147,16 +4213,6 @@ exit_dispatcher_thread:
                PERROR("pthread_join health_thread");
                retval = -1;
        }
-exit_health_thread:
-
-       utils_close_pipe(health_quit_pipe);
-exit_health_quit_pipe:
-
-exit_init_data:
-       health_app_destroy(health_relayd);
-       sessiond_trace_chunk_registry_destroy(sessiond_trace_chunk_registry);
-exit_health_app_create:
-exit_sessiond_trace_chunk_registry:
 exit_options:
        /*
         * Wait for all pending call_rcu work to complete before tearing
This page took 0.025993 seconds and 4 git commands to generate.