Launch the health management thread using lttng_thread
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 27 Nov 2018 17:39:06 +0000 (12:39 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 10 Dec 2018 20:24:49 +0000 (15:24 -0500)
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-sessiond/Makefile.am
src/bin/lttng-sessiond/health-sessiond.h
src/bin/lttng-sessiond/health.c [new file with mode: 0644]
src/bin/lttng-sessiond/main.c

index 6330cdccc55afc82d3e7ae20129f77d128f1adda..43962e7dffc69fd8e2896744d9420017f54adc84 100644 (file)
@@ -44,7 +44,8 @@ lttng_sessiond_SOURCES = utils.c utils.h \
                        globals.c \
                        thread-utils.c \
                        process-utils.c \
-                       thread.c thread.h
+                       thread.c thread.h \
+                       health.c
 
 if HAVE_LIBLTTNG_UST_CTL
 lttng_sessiond_SOURCES += trace-ust.c ust-registry.c ust-app.c \
index b9c3161fe3a001dba8ef16efbd0d424ce7f5172b..d62db2c380d42f5664896383a0997aa5ef73321e 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <lttng/health-internal.h>
+#include <stdbool.h>
 
 enum health_type_sessiond {
        HEALTH_SESSIOND_TYPE_CMD                = 0,
@@ -39,4 +40,6 @@ enum health_type_sessiond {
 /* Application health monitoring */
 extern struct health_app *health_sessiond;
 
+bool launch_health_management_thread(void);
+
 #endif /* HEALTH_SESSIOND_H */
diff --git a/src/bin/lttng-sessiond/health.c b/src/bin/lttng-sessiond/health.c
new file mode 100644 (file)
index 0000000..e2b8cc5
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
+ * Copyright (C) 2018 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "lttng-sessiond.h"
+#include "health-sessiond.h"
+#include <common/macros.h>
+#include <common/error.h>
+#include <common/utils.h>
+#include <common/pipe.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include "utils.h"
+#include "thread.h"
+
+static void cleanup_health_management_thread(void *thread_data)
+{
+       struct lttng_pipe *quit_pipe = thread_data;
+
+       lttng_pipe_destroy(quit_pipe);
+}
+
+/*
+ * Thread managing health check socket.
+ */
+static void *thread_manage_health(void *thread_data)
+{
+       const bool is_root = (getuid() == 0);
+       int sock = -1, new_sock = -1, ret, i, pollfd, err = -1;
+       uint32_t revents, nb_fd;
+       struct lttng_poll_event events;
+       struct health_comm_msg msg;
+       struct health_comm_reply reply;
+       /* Thread-specific quit pipe. */
+       struct lttng_pipe *quit_pipe = thread_data;
+       const int quit_pipe_read_fd = lttng_pipe_get_readfd(quit_pipe);
+
+       DBG("[thread] Manage health check started");
+
+       rcu_register_thread();
+
+       /*
+        * Created with a size of two for:
+        *   - client socket
+        *   - thread quit pipe
+        */
+       ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
+       if (ret < 0) {
+               goto error;
+       }
+
+       /* Create unix socket */
+       sock = lttcomm_create_unix_sock(config.health_unix_sock_path.value);
+       if (sock < 0) {
+               ERR("Unable to create health check Unix socket");
+               goto error;
+       }
+
+       if (is_root) {
+               /* lttng health client socket path permissions */
+               ret = chown(config.health_unix_sock_path.value, 0,
+                               utils_get_group_id(config.tracing_group_name.value));
+               if (ret < 0) {
+                       ERR("Unable to set group on %s", config.health_unix_sock_path.value);
+                       PERROR("chown");
+                       goto error;
+               }
+
+               ret = chmod(config.health_unix_sock_path.value,
+                               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+               if (ret < 0) {
+                       ERR("Unable to set permissions on %s", config.health_unix_sock_path.value);
+                       PERROR("chmod");
+                       goto error;
+               }
+       }
+
+       /*
+        * Set the CLOEXEC flag. Return code is useless because either way, the
+        * show must go on.
+        */
+       (void) utils_set_fd_cloexec(sock);
+
+       ret = lttcomm_listen_unix_sock(sock);
+       if (ret < 0) {
+               goto error;
+       }
+
+       ret = lttng_poll_add(&events, quit_pipe_read_fd, LPOLLIN | LPOLLERR);
+       if (ret < 0) {
+               goto error;
+       }
+
+       /* Add the application registration socket */
+       ret = lttng_poll_add(&events, sock, LPOLLIN | LPOLLPRI);
+       if (ret < 0) {
+               goto error;
+       }
+
+       sessiond_notify_ready();
+
+       while (1) {
+               DBG("Health check ready");
+
+               /* Infinite blocking call, waiting for transmission */
+restart:
+               ret = lttng_poll_wait(&events, -1);
+               if (ret < 0) {
+                       /*
+                        * Restart interrupted system call.
+                        */
+                       if (errno == EINTR) {
+                               goto restart;
+                       }
+                       goto error;
+               }
+
+               nb_fd = ret;
+
+               for (i = 0; i < nb_fd; i++) {
+                       /* Fetch once the poll data */
+                       revents = LTTNG_POLL_GETEV(&events, i);
+                       pollfd = LTTNG_POLL_GETFD(&events, i);
+
+                       if (!revents) {
+                               /* No activity for this FD (poll implementation). */
+                               continue;
+                       }
+
+                       /* Event on the registration socket */
+                       if (pollfd == sock) {
+                               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;
+                               }
+                       } else {
+                               /* Event on the thread's quit pipe. */
+                               err = 0;
+                               goto exit;
+                       }
+               }
+
+               new_sock = lttcomm_accept_unix_sock(sock);
+               if (new_sock < 0) {
+                       goto error;
+               }
+
+               /*
+                * Set the CLOEXEC flag. Return code is useless because either way, the
+                * show must go on.
+                */
+               (void) utils_set_fd_cloexec(new_sock);
+
+               DBG("Receiving data from client for health...");
+               ret = lttcomm_recv_unix_sock(new_sock, (void *)&msg, sizeof(msg));
+               if (ret <= 0) {
+                       DBG("Nothing recv() from client... continuing");
+                       ret = close(new_sock);
+                       if (ret) {
+                               PERROR("close");
+                       }
+                       continue;
+               }
+
+               rcu_thread_online();
+
+               memset(&reply, 0, sizeof(reply));
+               for (i = 0; i < NR_HEALTH_SESSIOND_TYPES; i++) {
+                       /*
+                        * health_check_state returns 0 if health is
+                        * bad.
+                        */
+                       if (!health_check_state(health_sessiond, i)) {
+                               reply.ret_code |= 1ULL << i;
+                       }
+               }
+
+               DBG2("Health check return value %" PRIx64, reply.ret_code);
+
+               ret = lttcomm_send_unix_sock(new_sock, (void *) &reply,
+                               sizeof(reply));
+               if (ret < 0) {
+                       ERR("Failed to send health data back to client");
+               }
+
+               /* End of transmission */
+               ret = close(new_sock);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
+
+exit:
+error:
+       if (err) {
+               ERR("Health error occurred in %s", __func__);
+       }
+       DBG("Health check thread dying");
+       unlink(config.health_unix_sock_path.value);
+       if (sock >= 0) {
+               ret = close(sock);
+               if (ret) {
+                       PERROR("close");
+               }
+       }
+
+       lttng_poll_clean(&events);
+       rcu_unregister_thread();
+       return NULL;
+}
+
+static bool shutdown_health_management_thread(void *thread_data)
+{
+       int ret;
+       int pipe_write_fd;
+       struct lttng_pipe *health_quit_pipe = thread_data;
+
+       pipe_write_fd = lttng_pipe_get_writefd(health_quit_pipe);
+       ret = notify_thread_pipe(pipe_write_fd);
+       if (ret < 0) {
+               ERR("Failed to notify Health management thread's quit pipe");
+               goto error;
+       }
+       return true;
+error:
+       return false;
+}
+
+bool launch_health_management_thread(void)
+{
+       struct lttng_thread *thread;
+       struct lttng_pipe *health_quit_pipe = NULL;
+
+       health_quit_pipe = lttng_pipe_open(FD_CLOEXEC);
+       if (!health_quit_pipe) {
+               goto error;
+       }
+
+       thread = lttng_thread_create("Health management",
+                       thread_manage_health,
+                       shutdown_health_management_thread,
+                       cleanup_health_management_thread,
+                       health_quit_pipe);
+       if (!thread) {
+               goto error;
+       }
+       lttng_thread_put(thread);
+       return true;
+error:
+       cleanup_health_management_thread(health_quit_pipe);
+       return false;
+}
index 7e4e2950b19e9cf1903a793553cca0351fa1b225..8820fdbddca9ee8e177063c290be0f917e92ea72 100644 (file)
@@ -192,7 +192,6 @@ static pthread_t reg_apps_thread;
 static pthread_t client_thread;
 static pthread_t kernel_thread;
 static pthread_t dispatch_thread;
-static pthread_t health_thread;
 static pthread_t agent_reg_thread;
 static pthread_t load_session_thread;
 static pthread_t notification_thread;
@@ -4195,196 +4194,6 @@ init_setup_error:
        return ret;
 }
 
-/*
- * Thread managing health check socket.
- */
-static void *thread_manage_health(void *data)
-{
-       int sock = -1, new_sock = -1, ret, i, pollfd, err = -1;
-       uint32_t revents, nb_fd;
-       struct lttng_poll_event events;
-       struct health_comm_msg msg;
-       struct health_comm_reply reply;
-
-       DBG("[thread] Manage health check started");
-
-       rcu_register_thread();
-
-       /* We might hit an error path before this is created. */
-       lttng_poll_init(&events);
-
-       /* Create unix socket */
-       sock = lttcomm_create_unix_sock(config.health_unix_sock_path.value);
-       if (sock < 0) {
-               ERR("Unable to create health check Unix socket");
-               goto error;
-       }
-
-       if (is_root) {
-               /* lttng health client socket path permissions */
-               ret = chown(config.health_unix_sock_path.value, 0,
-                               utils_get_group_id(config.tracing_group_name.value));
-               if (ret < 0) {
-                       ERR("Unable to set group on %s", config.health_unix_sock_path.value);
-                       PERROR("chown");
-                       goto error;
-               }
-
-               ret = chmod(config.health_unix_sock_path.value,
-                               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
-               if (ret < 0) {
-                       ERR("Unable to set permissions on %s", config.health_unix_sock_path.value);
-                       PERROR("chmod");
-                       goto error;
-               }
-       }
-
-       /*
-        * Set the CLOEXEC flag. Return code is useless because either way, the
-        * show must go on.
-        */
-       (void) utils_set_fd_cloexec(sock);
-
-       ret = lttcomm_listen_unix_sock(sock);
-       if (ret < 0) {
-               goto error;
-       }
-
-       /*
-        * Pass 2 as size here for the thread quit pipe and client_sock. Nothing
-        * more will be added to this poll set.
-        */
-       ret = sessiond_set_thread_pollset(&events, 2);
-       if (ret < 0) {
-               goto error;
-       }
-
-       /* Add the application registration socket */
-       ret = lttng_poll_add(&events, sock, LPOLLIN | LPOLLPRI);
-       if (ret < 0) {
-               goto error;
-       }
-
-       sessiond_notify_ready();
-
-       while (1) {
-               DBG("Health check ready");
-
-               /* Inifinite blocking call, waiting for transmission */
-restart:
-               ret = lttng_poll_wait(&events, -1);
-               if (ret < 0) {
-                       /*
-                        * Restart interrupted system call.
-                        */
-                       if (errno == EINTR) {
-                               goto restart;
-                       }
-                       goto error;
-               }
-
-               nb_fd = ret;
-
-               for (i = 0; i < nb_fd; i++) {
-                       /* Fetch once the poll data */
-                       revents = LTTNG_POLL_GETEV(&events, i);
-                       pollfd = LTTNG_POLL_GETFD(&events, i);
-
-                       if (!revents) {
-                               /* No activity for this FD (poll implementation). */
-                               continue;
-                       }
-
-                       /* Thread quit pipe has been closed. Killing thread. */
-                       ret = sessiond_check_thread_quit_pipe(pollfd, revents);
-                       if (ret) {
-                               err = 0;
-                               goto exit;
-                       }
-
-                       /* Event on the registration socket */
-                       if (pollfd == sock) {
-                               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;
-                               }
-                       }
-               }
-
-               new_sock = lttcomm_accept_unix_sock(sock);
-               if (new_sock < 0) {
-                       goto error;
-               }
-
-               /*
-                * Set the CLOEXEC flag. Return code is useless because either way, the
-                * show must go on.
-                */
-               (void) utils_set_fd_cloexec(new_sock);
-
-               DBG("Receiving data from client for health...");
-               ret = lttcomm_recv_unix_sock(new_sock, (void *)&msg, sizeof(msg));
-               if (ret <= 0) {
-                       DBG("Nothing recv() from client... continuing");
-                       ret = close(new_sock);
-                       if (ret) {
-                               PERROR("close");
-                       }
-                       continue;
-               }
-
-               rcu_thread_online();
-
-               memset(&reply, 0, sizeof(reply));
-               for (i = 0; i < NR_HEALTH_SESSIOND_TYPES; i++) {
-                       /*
-                        * health_check_state returns 0 if health is
-                        * bad.
-                        */
-                       if (!health_check_state(health_sessiond, i)) {
-                               reply.ret_code |= 1ULL << i;
-                       }
-               }
-
-               DBG2("Health check return value %" PRIx64, reply.ret_code);
-
-               ret = send_unix_sock(new_sock, (void *) &reply, sizeof(reply));
-               if (ret < 0) {
-                       ERR("Failed to send health data back to client");
-               }
-
-               /* End of transmission */
-               ret = close(new_sock);
-               if (ret) {
-                       PERROR("close");
-               }
-       }
-
-exit:
-error:
-       if (err) {
-               ERR("Health error occurred in %s", __func__);
-       }
-       DBG("Health check thread dying");
-       unlink(config.health_unix_sock_path.value);
-       if (sock >= 0) {
-               ret = close(sock);
-               if (ret) {
-                       PERROR("close");
-               }
-       }
-
-       lttng_poll_clean(&events);
-       stop_threads();
-       rcu_unregister_thread();
-       return NULL;
-}
-
 /*
  * This thread manage all clients request using the unix client socket for
  * communication.
@@ -6039,11 +5848,7 @@ int main(int argc, char **argv)
        load_info->path = config.load_session_path.value;
 
        /* Create health-check thread. */
-       ret = pthread_create(&health_thread, default_pthread_attr(),
-                       thread_manage_health, (void *) NULL);
-       if (ret) {
-               errno = ret;
-               PERROR("pthread_create health");
+       if (!launch_health_management_thread()) {
                retval = -1;
                goto exit_health;
        }
@@ -6289,14 +6094,7 @@ exit_client:
 exit_rotation:
 exit_notification:
        sem_destroy(&notification_thread_ready);
-       ret = pthread_join(health_thread, &status);
-       if (ret) {
-               errno = ret;
-               PERROR("pthread_join health thread");
-               retval = -1;
-       }
        lttng_thread_list_shutdown_orphans();
-
 exit_health:
 exit_init_data:
        /*
This page took 0.035166 seconds and 4 git commands to generate.