Commit | Line | Data |
---|---|---|
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 | */ | |
35 | static const char *default_reg_uri = "tcp://localhost"; | |
36 | ||
37 | /* | |
38 | * Create and init socket from uri. | |
39 | */ | |
40 | static 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 | ||
82 | error: | |
83 | if (sock) { | |
84 | lttcomm_destroy_sock(sock); | |
85 | } | |
86 | return NULL; | |
87 | } | |
88 | ||
89 | /* | |
90 | * Close and destroy the given TCP socket. | |
91 | */ | |
92 | static 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 | */ | |
106 | void *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 */ | |
141 | restart: | |
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 | ||
189 | exit: | |
190 | error: | |
191 | destroy_tcp_socket(reg_sock); | |
192 | error_tcp_socket: | |
193 | lttng_poll_clean(&events); | |
194 | error_poll_create: | |
195 | DBG("[jul-thread] is cleaning up and stopping."); | |
196 | ||
197 | rcu_thread_offline(); | |
198 | rcu_unregister_thread(); | |
199 | return NULL; | |
200 | } |