Add JUL registration thread
authorDavid Goulet <dgoulet@efficios.com>
Mon, 30 Sep 2013 21:28:16 +0000 (17:28 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Wed, 16 Oct 2013 14:19:12 +0000 (10:19 -0400)
Listening on port 5345 by default and adds the --jul-tcp-port option to
the session daemon command line options.

At this commit, the thread is started and listening for incoming
registration but they are not handled.

This commit adds a new thread to the session daemon that is spawned by
default once the launched.

Signed-off-by: David Goulet <dgoulet@efficios.com>
src/bin/lttng-sessiond/Makefile.am
src/bin/lttng-sessiond/jul-thread.c [new file with mode: 0644]
src/bin/lttng-sessiond/jul-thread.h [new file with mode: 0644]
src/bin/lttng-sessiond/lttng-sessiond.h
src/bin/lttng-sessiond/main.c
src/common/defaults.h

index 21b58591056512bae0f7ccedd66cb2dd0169b790..60cf0feeb741c58546527d554069d2666934a738 100644 (file)
@@ -27,7 +27,7 @@ lttng_sessiond_SOURCES = utils.c utils.h \
                        buffer-registry.c buffer-registry.h \
                        testpoint.h ht-cleanup.c \
                        snapshot.c snapshot.h \
-                       jul.c jul.h
+                       jul.c jul.h jul-thread.c jul-thread.h
 
 if HAVE_LIBLTTNG_UST_CTL
 lttng_sessiond_SOURCES += trace-ust.c ust-registry.c ust-app.c \
diff --git a/src/bin/lttng-sessiond/jul-thread.c b/src/bin/lttng-sessiond/jul-thread.c
new file mode 100644 (file)
index 0000000..9bc82ea
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@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.
+ */
+
+#define _GNU_SOURCE
+#include <assert.h>
+
+#include <common/common.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/uri.h>
+#include <common/utils.h>
+
+#include "fd-limit.h"
+#include "jul-thread.h"
+#include "lttng-sessiond.h"
+
+/*
+ * Note that there is not port here. It's set after this URI is parsed so we
+ * can let the user define a custom one. However, localhost is ALWAYS the
+ * default listening address.
+ */
+static const char *default_reg_uri = "tcp://localhost";
+
+/*
+ * Create and init socket from uri.
+ */
+static struct lttcomm_sock *init_tcp_socket(void)
+{
+       int ret;
+       struct lttng_uri *uri = NULL;
+       struct lttcomm_sock *sock = NULL;
+
+       /*
+        * This should never fail since the URI is hardcoded and the port is set
+        * before this thread is launched.
+        */
+       ret = uri_parse(default_reg_uri, &uri);
+       assert(ret);
+       assert(jul_tcp_port);
+       uri->port = jul_tcp_port;
+
+       sock = lttcomm_alloc_sock_from_uri(uri);
+       uri_free(uri);
+       if (sock == NULL) {
+               ERR("[jul-thread] JUL allocating TCP socket");
+               goto error;
+       }
+
+       ret = lttcomm_create_sock(sock);
+       if (ret < 0) {
+               goto error;
+       }
+
+       ret = sock->ops->bind(sock);
+       if (ret < 0) {
+               goto error;
+       }
+
+       ret = sock->ops->listen(sock, -1);
+       if (ret < 0) {
+               goto error;
+       }
+
+       DBG("[jul-thread] Listening on TCP port %u and socket %d", jul_tcp_port,
+                       sock->fd);
+
+       return sock;
+
+error:
+       if (sock) {
+               lttcomm_destroy_sock(sock);
+       }
+       return NULL;
+}
+
+/*
+ * Close and destroy the given TCP socket.
+ */
+static void destroy_tcp_socket(struct lttcomm_sock *sock)
+{
+       assert(sock);
+
+       DBG3("[jul-thread] Destroy TCP socket on port %u", jul_tcp_port);
+
+       /* This will return gracefully if fd is invalid. */
+       sock->ops->close(sock);
+       lttcomm_destroy_sock(sock);
+}
+
+/*
+ * This thread manage application notify communication.
+ */
+void *jul_thread_manage_registration(void *data)
+{
+       int i, ret, pollfd;
+       uint32_t revents, nb_fd;
+       struct lttng_poll_event events;
+       struct lttcomm_sock *reg_sock;
+
+       DBG("[jul-thread] Manage JUL application registration.");
+
+       rcu_register_thread();
+       rcu_thread_online();
+
+       /* Create pollset with size 2, quit pipe and socket. */
+       ret = sessiond_set_thread_pollset(&events, 2);
+       if (ret < 0) {
+               goto error_poll_create;
+       }
+
+       reg_sock = init_tcp_socket();
+       if (!reg_sock) {
+               goto error_tcp_socket;
+       }
+
+       /* Add create valid TCP socket to poll set. */
+       ret = lttng_poll_add(&events, reg_sock->fd,
+                       LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP);
+       if (ret < 0) {
+               goto error;
+       }
+
+       while (1) {
+               DBG3("[jul-thread] Manage JUL polling on %d fds",
+                               LTTNG_POLL_GETNB(&events));
+
+               /* 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);
+
+                       /* Thread quit pipe has been closed. Killing thread. */
+                       ret = sessiond_check_thread_quit_pipe(pollfd, revents);
+                       if (ret) {
+                               goto exit;
+                       }
+
+                       /*
+                        * Check first if this is a POLLERR since POLLIN is also included
+                        * in an error value thus checking first.
+                        */
+                       if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+                               /* Removing from the poll set */
+                               ret = lttng_poll_del(&events, pollfd);
+                               if (ret < 0) {
+                                       goto error;
+                               }
+
+                               /* FIXME: Nullify the JUL socket for the associated ust app. */
+                       } else if (revents & (LPOLLIN | LPOLLPRI)) {
+                               /*
+                                * FIXME: Handle JUL registration which must link an UST-app
+                                * and this JUL socket.
+                                */
+                       } else {
+                               ERR("Unknown poll events %u for sock %d", revents, pollfd);
+                               continue;
+                       }
+               }
+       }
+
+exit:
+error:
+       destroy_tcp_socket(reg_sock);
+error_tcp_socket:
+       lttng_poll_clean(&events);
+error_poll_create:
+       DBG("[jul-thread] is cleaning up and stopping.");
+
+       rcu_thread_offline();
+       rcu_unregister_thread();
+       return NULL;
+}
diff --git a/src/bin/lttng-sessiond/jul-thread.h b/src/bin/lttng-sessiond/jul-thread.h
new file mode 100644 (file)
index 0000000..58bdad7
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@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.
+ */
+
+#ifndef _JUL_THREAD_H
+#define _JUL_THREAD_H
+
+#ifdef HAVE_LIBLTTNG_UST_CTL
+
+void *jul_thread_manage_registration(void *data);
+
+#else /* HAVE_LIBLTTNG_UST_CTL */
+
+void *jul_thread_manage_registration(void *data);
+{
+       return NULL;
+}
+
+#endif /* HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* _JUL_THREAD_H */
index aeb03037073f67dedab460903482891ccb5489e5..e21f6d0126c66bf3903683e4caadb8b1078ab557 100644 (file)
@@ -103,6 +103,11 @@ extern int ht_cleanup_pipe[2];
  */
 extern long page_size;
 
+/*
+ * Global set once in main(). JUL TCP port for registration.
+ */
+extern unsigned int jul_tcp_port;
+
 int sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size);
 int sessiond_check_thread_quit_pipe(int fd, uint32_t events);
 
index 028f5f9d233a0933ddd9199e9171bf620065fbba..6d6140b1f891f10c75f4cff539c0f6776b7272aa 100644 (file)
@@ -63,6 +63,7 @@
 #include "health-sessiond.h"
 #include "testpoint.h"
 #include "ust-thread.h"
+#include "jul-thread.h"
 
 #define CONSUMERD_FILE "lttng-consumerd"
 
@@ -156,6 +157,7 @@ static pthread_t kernel_thread;
 static pthread_t dispatch_thread;
 static pthread_t health_thread;
 static pthread_t ht_cleanup_thread;
+static pthread_t jul_reg_thread;
 
 /*
  * UST registration command queue. This queue is tied with a futex and uses a N
@@ -233,6 +235,9 @@ long page_size;
 /* Application health monitoring */
 struct health_app *health_sessiond;
 
+/* JUL TCP port for registration. Used by the JUL thread. */
+unsigned int jul_tcp_port = DEFAULT_JUL_TCP_PORT;
+
 static
 void setup_consumerd_path(void)
 {
@@ -3917,6 +3922,7 @@ static void usage(void)
        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");
+       fprintf(stderr, "      --jul-tcp-port                 JUL application registration TCP port\n");
 }
 
 /*
@@ -3949,12 +3955,13 @@ static int parse_args(int argc, char **argv)
                { "verbose-consumer", 0, 0, 'Z' },
                { "no-kernel", 0, 0, 'N' },
                { "pidfile", 1, 0, 'p' },
+               { "jul-tcp-port", 1, 0, 'J' },
                { 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:p:",
+               c = getopt_long(argc, argv, "dhqvVSN" "a:c:g:s:C:E:D:F:Z:u:t:p:J:",
                                long_options, &option_index);
                if (c == -1) {
                        break;
@@ -4034,6 +4041,24 @@ static int parse_args(int argc, char **argv)
                case 'p':
                        opt_pidfile = optarg;
                        break;
+               case 'J': /* JUL TCP port. */
+               {
+                       unsigned long v;
+
+                       errno = 0;
+                       v = strtoul(optarg, NULL, 0);
+                       if (errno != 0 || !isdigit(optarg[0])) {
+                               ERR("Wrong value in --jul-tcp-port parameter: %s", optarg);
+                               return -1;
+                       }
+                       if (v == 0 || v >= 65535) {
+                               ERR("Port overflow in --jul-tcp-port parameter: %s", optarg);
+                               return -1;
+                       }
+                       jul_tcp_port = (uint32_t) v;
+                       DBG3("JUL TCP port set to non default: %u", jul_tcp_port);
+                       break;
+               }
                default:
                        /* Unknown option or other error.
                         * Error is printed by getopt, just return */
@@ -4778,6 +4803,14 @@ int main(int argc, char **argv)
                goto exit_apps_notify;
        }
 
+       /* Create JUL registration thread. */
+       ret = pthread_create(&jul_reg_thread, NULL,
+                       jul_thread_manage_registration, (void *) NULL);
+       if (ret != 0) {
+               PERROR("pthread_create apps");
+               goto exit_jul_reg;
+       }
+
        /* Don't start this thread if kernel tracing is not requested nor root */
        if (is_root && !opt_no_kernel) {
                /* Create kernel thread to manage kernel event */
@@ -4796,6 +4829,13 @@ int main(int argc, char **argv)
        }
 
 exit_kernel:
+       ret = pthread_join(jul_reg_thread, &status);
+       if (ret != 0) {
+               PERROR("pthread_join JUL");
+               goto error;     /* join error, exit without cleanup */
+       }
+
+exit_jul_reg:
        ret = pthread_join(apps_notify_thread, &status);
        if (ret != 0) {
                PERROR("pthread_join apps notify");
index 0682af63df6eb4904698c5aa0b9b99f8f5a61027..0010e0616bd18862ab2cb5459709871d2a1571e9 100644 (file)
 #define DEFAULT_NETWORK_DATA_PORT           5343
 #define DEFAULT_NETWORK_VIEWER_PORT         5344
 
+/* JUL registration TCP port. */
+#define DEFAULT_JUL_TCP_PORT                5345
+
 /*
  * If a thread stalls for this amount of time, it will be considered bogus (bad
  * health).
This page took 0.03025 seconds and 4 git commands to generate.