From 4d0762229f4950d4ad21f6f47870d3b767dd61fa Mon Sep 17 00:00:00 2001 From: David Goulet Date: Mon, 30 Sep 2013 17:28:16 -0400 Subject: [PATCH] Add JUL registration thread 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 --- src/bin/lttng-sessiond/Makefile.am | 2 +- src/bin/lttng-sessiond/jul-thread.c | 200 ++++++++++++++++++++++++ src/bin/lttng-sessiond/jul-thread.h | 34 ++++ src/bin/lttng-sessiond/lttng-sessiond.h | 5 + src/bin/lttng-sessiond/main.c | 42 ++++- src/common/defaults.h | 3 + 6 files changed, 284 insertions(+), 2 deletions(-) create mode 100644 src/bin/lttng-sessiond/jul-thread.c create mode 100644 src/bin/lttng-sessiond/jul-thread.h diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am index 21b585910..60cf0feeb 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -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 index 000000000..9bc82eac7 --- /dev/null +++ b/src/bin/lttng-sessiond/jul-thread.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2013 - David Goulet + * + * 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 + +#include +#include +#include +#include + +#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 index 000000000..58bdad72c --- /dev/null +++ b/src/bin/lttng-sessiond/jul-thread.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013 - David Goulet + * + * 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 */ diff --git a/src/bin/lttng-sessiond/lttng-sessiond.h b/src/bin/lttng-sessiond/lttng-sessiond.h index aeb030370..e21f6d012 100644 --- a/src/bin/lttng-sessiond/lttng-sessiond.h +++ b/src/bin/lttng-sessiond/lttng-sessiond.h @@ -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); diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 028f5f9d2..6d6140b1f 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -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"); diff --git a/src/common/defaults.h b/src/common/defaults.h index 0682af63d..0010e0616 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -203,6 +203,9 @@ #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). -- 2.34.1