Add JUL registration thread
[lttng-tools.git] / src / bin / lttng-sessiond / jul-thread.c
CommitLineData
4d076222
DG
1/*
2 * Copyright (C) 2013 - David Goulet <dgoulet@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _GNU_SOURCE
19#include <assert.h>
20
21#include <common/common.h>
22#include <common/sessiond-comm/sessiond-comm.h>
23#include <common/uri.h>
24#include <common/utils.h>
25
26#include "fd-limit.h"
27#include "jul-thread.h"
28#include "lttng-sessiond.h"
29
30/*
31 * Note that there is not port here. It's set after this URI is parsed so we
32 * can let the user define a custom one. However, localhost is ALWAYS the
33 * default listening address.
34 */
35static const char *default_reg_uri = "tcp://localhost";
36
37/*
38 * Create and init socket from uri.
39 */
40static struct lttcomm_sock *init_tcp_socket(void)
41{
42 int ret;
43 struct lttng_uri *uri = NULL;
44 struct lttcomm_sock *sock = NULL;
45
46 /*
47 * This should never fail since the URI is hardcoded and the port is set
48 * before this thread is launched.
49 */
50 ret = uri_parse(default_reg_uri, &uri);
51 assert(ret);
52 assert(jul_tcp_port);
53 uri->port = jul_tcp_port;
54
55 sock = lttcomm_alloc_sock_from_uri(uri);
56 uri_free(uri);
57 if (sock == NULL) {
58 ERR("[jul-thread] JUL allocating TCP socket");
59 goto error;
60 }
61
62 ret = lttcomm_create_sock(sock);
63 if (ret < 0) {
64 goto error;
65 }
66
67 ret = sock->ops->bind(sock);
68 if (ret < 0) {
69 goto error;
70 }
71
72 ret = sock->ops->listen(sock, -1);
73 if (ret < 0) {
74 goto error;
75 }
76
77 DBG("[jul-thread] Listening on TCP port %u and socket %d", jul_tcp_port,
78 sock->fd);
79
80 return sock;
81
82error:
83 if (sock) {
84 lttcomm_destroy_sock(sock);
85 }
86 return NULL;
87}
88
89/*
90 * Close and destroy the given TCP socket.
91 */
92static void destroy_tcp_socket(struct lttcomm_sock *sock)
93{
94 assert(sock);
95
96 DBG3("[jul-thread] Destroy TCP socket on port %u", jul_tcp_port);
97
98 /* This will return gracefully if fd is invalid. */
99 sock->ops->close(sock);
100 lttcomm_destroy_sock(sock);
101}
102
103/*
104 * This thread manage application notify communication.
105 */
106void *jul_thread_manage_registration(void *data)
107{
108 int i, ret, pollfd;
109 uint32_t revents, nb_fd;
110 struct lttng_poll_event events;
111 struct lttcomm_sock *reg_sock;
112
113 DBG("[jul-thread] Manage JUL application registration.");
114
115 rcu_register_thread();
116 rcu_thread_online();
117
118 /* Create pollset with size 2, quit pipe and socket. */
119 ret = sessiond_set_thread_pollset(&events, 2);
120 if (ret < 0) {
121 goto error_poll_create;
122 }
123
124 reg_sock = init_tcp_socket();
125 if (!reg_sock) {
126 goto error_tcp_socket;
127 }
128
129 /* Add create valid TCP socket to poll set. */
130 ret = lttng_poll_add(&events, reg_sock->fd,
131 LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP);
132 if (ret < 0) {
133 goto error;
134 }
135
136 while (1) {
137 DBG3("[jul-thread] Manage JUL polling on %d fds",
138 LTTNG_POLL_GETNB(&events));
139
140 /* Inifinite blocking call, waiting for transmission */
141restart:
142 ret = lttng_poll_wait(&events, -1);
143 if (ret < 0) {
144 /*
145 * Restart interrupted system call.
146 */
147 if (errno == EINTR) {
148 goto restart;
149 }
150 goto error;
151 }
152 nb_fd = ret;
153
154 for (i = 0; i < nb_fd; i++) {
155 /* Fetch once the poll data */
156 revents = LTTNG_POLL_GETEV(&events, i);
157 pollfd = LTTNG_POLL_GETFD(&events, i);
158
159 /* Thread quit pipe has been closed. Killing thread. */
160 ret = sessiond_check_thread_quit_pipe(pollfd, revents);
161 if (ret) {
162 goto exit;
163 }
164
165 /*
166 * Check first if this is a POLLERR since POLLIN is also included
167 * in an error value thus checking first.
168 */
169 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
170 /* Removing from the poll set */
171 ret = lttng_poll_del(&events, pollfd);
172 if (ret < 0) {
173 goto error;
174 }
175
176 /* FIXME: Nullify the JUL socket for the associated ust app. */
177 } else if (revents & (LPOLLIN | LPOLLPRI)) {
178 /*
179 * FIXME: Handle JUL registration which must link an UST-app
180 * and this JUL socket.
181 */
182 } else {
183 ERR("Unknown poll events %u for sock %d", revents, pollfd);
184 continue;
185 }
186 }
187 }
188
189exit:
190error:
191 destroy_tcp_socket(reg_sock);
192error_tcp_socket:
193 lttng_poll_clean(&events);
194error_poll_create:
195 DBG("[jul-thread] is cleaning up and stopping.");
196
197 rcu_thread_offline();
198 rcu_unregister_thread();
199 return NULL;
200}
This page took 0.046141 seconds and 5 git commands to generate.