fix: relayd: unaligned access in trace_chunk_registry_ht_key_hash
[lttng-tools.git] / src / bin / lttng-sessiond / register.cpp
1 /*
2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-only
7 *
8 */
9
10 #include "fd-limit.hpp"
11 #include "health-sessiond.hpp"
12 #include "lttng-sessiond.hpp"
13 #include "register.hpp"
14 #include "testpoint.hpp"
15 #include "thread.hpp"
16 #include "utils.hpp"
17
18 #include <common/futex.hpp>
19 #include <common/macros.hpp>
20 #include <common/shm.hpp>
21 #include <common/utils.hpp>
22
23 #include <fcntl.h>
24 #include <stddef.h>
25 #include <stdlib.h>
26 #include <sys/stat.h>
27 #include <urcu.h>
28
29 namespace {
30 struct thread_state {
31 struct lttng_pipe *quit_pipe;
32 struct ust_cmd_queue *ust_cmd_queue;
33 sem_t ready;
34 bool running;
35 int application_socket;
36 };
37 } /* namespace */
38
39 /*
40 * Creates the application socket.
41 */
42 static int create_application_socket()
43 {
44 int ret = 0;
45 int apps_sock;
46
47 /* Create the application unix socket */
48 apps_sock = lttcomm_create_unix_sock(the_config.apps_unix_sock_path.value);
49 if (apps_sock < 0) {
50 ERR("Create unix sock failed: %s", the_config.apps_unix_sock_path.value);
51 ret = -1;
52 goto end;
53 }
54
55 /* Set the cloexec flag */
56 ret = utils_set_fd_cloexec(apps_sock);
57 if (ret < 0) {
58 ERR("Unable to set CLOEXEC flag to the app Unix socket (fd: %d). "
59 "Continuing but note that the consumer daemon will have a "
60 "reference to this socket on exec()",
61 apps_sock);
62 }
63
64 /* File permission MUST be 666 */
65 ret = chmod(the_config.apps_unix_sock_path.value,
66 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
67 if (ret < 0) {
68 PERROR("Set file permissions failed on %s", the_config.apps_unix_sock_path.value);
69 goto error_close_socket;
70 }
71
72 DBG3("Session daemon application socket created (fd = %d) ", apps_sock);
73 ret = apps_sock;
74 end:
75 return ret;
76 error_close_socket:
77 if (close(apps_sock)) {
78 PERROR("Failed to close application socket in error path");
79 }
80 apps_sock = -1;
81 ret = -1;
82 goto end;
83 }
84
85 /*
86 * Notify UST applications using the shm mmap futex.
87 */
88 static int notify_ust_apps(int active, bool is_root)
89 {
90 char *wait_shm_mmap;
91
92 DBG("Notifying applications of session daemon state: %d", active);
93
94 /* See shm.c for this call implying mmap, shm and futex calls */
95 wait_shm_mmap = shm_ust_get_mmap(the_config.wait_shm_path.value, is_root);
96 if (wait_shm_mmap == nullptr) {
97 goto error;
98 }
99
100 /* Wake waiting process */
101 futex_wait_update((int32_t *) wait_shm_mmap, active);
102
103 /* Apps notified successfully */
104 return 0;
105
106 error:
107 return -1;
108 }
109
110 static void cleanup_application_registration_thread(void *data)
111 {
112 struct thread_state *thread_state = (struct thread_state *) data;
113
114 if (!data) {
115 return;
116 }
117
118 lttng_pipe_destroy(thread_state->quit_pipe);
119 free(thread_state);
120 }
121
122 static void set_thread_status(struct thread_state *thread_state, bool running)
123 {
124 DBG("Marking application registration thread's state as %s", running ? "running" : "error");
125 thread_state->running = running;
126 sem_post(&thread_state->ready);
127 }
128
129 static bool wait_thread_status(struct thread_state *thread_state)
130 {
131 DBG("Waiting for application registration thread to be ready");
132 sem_wait(&thread_state->ready);
133 if (thread_state->running) {
134 DBG("Application registration thread is ready");
135 } else {
136 ERR("Initialization of application registration thread failed");
137 }
138
139 return thread_state->running;
140 }
141
142 static void thread_init_cleanup(void *data)
143 {
144 struct thread_state *thread_state = (struct thread_state *) data;
145
146 set_thread_status(thread_state, false);
147 }
148
149 /*
150 * This thread manage application registration.
151 */
152 static void *thread_application_registration(void *data)
153 {
154 int sock = -1, i, ret, err = -1;
155 uint32_t nb_fd;
156 struct lttng_poll_event events;
157 /*
158 * Gets allocated in this thread, enqueued to a global queue, dequeued
159 * and freed in the manage apps thread.
160 */
161 struct ust_command *ust_cmd = nullptr;
162 const bool is_root = (getuid() == 0);
163 struct thread_state *thread_state = (struct thread_state *) data;
164 const int application_socket = thread_state->application_socket;
165 const auto thread_quit_pipe_fd = lttng_pipe_get_readfd(thread_state->quit_pipe);
166
167 DBG("[thread] Manage application registration started");
168
169 pthread_cleanup_push(thread_init_cleanup, thread_state);
170 health_register(the_health_sessiond, HEALTH_SESSIOND_TYPE_APP_REG);
171
172 ret = lttcomm_listen_unix_sock(application_socket);
173 if (ret < 0) {
174 goto error_listen;
175 }
176
177 /*
178 * Pass 2 as size here for the thread quit pipe and apps_sock. Nothing
179 * more will be added to this poll set.
180 */
181 ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
182 if (ret < 0) {
183 goto error_create_poll;
184 }
185
186 /* Add the application registration socket */
187 ret = lttng_poll_add(&events, application_socket, LPOLLIN | LPOLLRDHUP);
188 if (ret < 0) {
189 goto error_poll_add;
190 }
191
192 /* Add the application registration socket */
193 ret = lttng_poll_add(&events, thread_quit_pipe_fd, LPOLLIN | LPOLLRDHUP);
194 if (ret < 0) {
195 goto error_poll_add;
196 }
197
198 set_thread_status(thread_state, true);
199 pthread_cleanup_pop(0);
200
201 if (testpoint(sessiond_thread_registration_apps)) {
202 goto error_poll_add;
203 }
204
205 while (true) {
206 DBG("Accepting application registration");
207
208 /* Inifinite blocking call, waiting for transmission */
209 restart:
210 health_poll_entry();
211 ret = lttng_poll_wait(&events, -1);
212 health_poll_exit();
213 if (ret < 0) {
214 /*
215 * Restart interrupted system call.
216 */
217 if (errno == EINTR) {
218 goto restart;
219 }
220 goto error;
221 }
222
223 nb_fd = ret;
224
225 for (i = 0; i < nb_fd; i++) {
226 health_code_update();
227
228 /* Fetch once the poll data */
229 const auto revents = LTTNG_POLL_GETEV(&events, i);
230 const auto pollfd = LTTNG_POLL_GETFD(&events, i);
231
232 /* Activity on thread quit pipe, closing. */
233 if (pollfd == thread_quit_pipe_fd) {
234 err = 0;
235 goto exit;
236 }
237
238 /* Event on the registration socket. */
239 if (revents & LPOLLIN) {
240 sock = lttcomm_accept_unix_sock(application_socket);
241 if (sock < 0) {
242 goto error;
243 }
244
245 /*
246 * Set socket timeout for both receiving and ending.
247 * app_socket_timeout is in seconds, whereas
248 * lttcomm_setsockopt_rcv_timeout and
249 * lttcomm_setsockopt_snd_timeout expect msec as
250 * parameter.
251 */
252 if (the_config.app_socket_timeout >= 0) {
253 (void) lttcomm_setsockopt_rcv_timeout(
254 sock, the_config.app_socket_timeout * 1000);
255 (void) lttcomm_setsockopt_snd_timeout(
256 sock, the_config.app_socket_timeout * 1000);
257 }
258
259 /*
260 * Set the CLOEXEC flag. Return code is useless because
261 * either way, the show must go on.
262 */
263 (void) utils_set_fd_cloexec(sock);
264
265 /* Create UST registration command for enqueuing */
266 ust_cmd = zmalloc<ust_command>();
267 if (ust_cmd == nullptr) {
268 PERROR("ust command zmalloc");
269 ret = close(sock);
270 if (ret) {
271 PERROR("close");
272 }
273 sock = -1;
274 goto error;
275 }
276
277 /*
278 * Using message-based transmissions to ensure we don't
279 * have to deal with partially received messages.
280 */
281 ret = lttng_fd_get(LTTNG_FD_APPS, 1);
282 if (ret < 0) {
283 ERR("Exhausted file descriptors allowed for applications.");
284 free(ust_cmd);
285 ret = close(sock);
286 if (ret) {
287 PERROR("close");
288 }
289 sock = -1;
290 continue;
291 }
292
293 health_code_update();
294 ret = ust_app_recv_registration(sock, &ust_cmd->reg_msg);
295 if (ret < 0) {
296 free(ust_cmd);
297 /* Close socket of the application. */
298 ret = close(sock);
299 if (ret) {
300 PERROR("close");
301 }
302 lttng_fd_put(LTTNG_FD_APPS, 1);
303 sock = -1;
304 continue;
305 }
306 health_code_update();
307
308 ust_cmd->sock = sock;
309 sock = -1;
310
311 DBG("UST registration received with pid:%d ppid:%d uid:%d"
312 " gid:%d sock:%d name:%s (version %d.%d)",
313 ust_cmd->reg_msg.pid,
314 ust_cmd->reg_msg.ppid,
315 ust_cmd->reg_msg.uid,
316 ust_cmd->reg_msg.gid,
317 ust_cmd->sock,
318 ust_cmd->reg_msg.name,
319 ust_cmd->reg_msg.major,
320 ust_cmd->reg_msg.minor);
321
322 /*
323 * Lock free enqueue the registration request. The red pill
324 * has been taken! This apps will be part of the *system*.
325 */
326 cds_wfcq_head_ptr_t head;
327 head.h = &thread_state->ust_cmd_queue->head;
328 cds_wfcq_enqueue(
329 head, &thread_state->ust_cmd_queue->tail, &ust_cmd->node);
330
331 /*
332 * Wake the registration queue futex. Implicit memory
333 * barrier with the exchange in cds_wfcq_enqueue.
334 */
335 futex_nto1_wake(&thread_state->ust_cmd_queue->futex);
336 } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
337 ERR("Register apps socket poll error");
338 goto error;
339 } else {
340 ERR("Unexpected poll events %u for sock %d", revents, pollfd);
341 goto error;
342 }
343 }
344 }
345
346 exit:
347 error:
348 /* Notify that the registration thread is gone */
349 notify_ust_apps(0, is_root);
350
351 ret = close(application_socket);
352 if (ret) {
353 PERROR("Failed to close application registration socket");
354 }
355 if (sock >= 0) {
356 ret = close(sock);
357 if (ret) {
358 PERROR("Failed to close application socket");
359 }
360 lttng_fd_put(LTTNG_FD_APPS, 1);
361 }
362 unlink(the_config.apps_unix_sock_path.value);
363
364 error_poll_add:
365 lttng_poll_clean(&events);
366 error_listen:
367 error_create_poll:
368 DBG("UST Registration thread cleanup complete");
369 if (err) {
370 health_error();
371 ERR("Health error occurred in %s", __func__);
372 }
373 health_unregister(the_health_sessiond);
374 return nullptr;
375 }
376
377 static bool shutdown_application_registration_thread(void *data)
378 {
379 struct thread_state *thread_state = (struct thread_state *) data;
380 const int write_fd = lttng_pipe_get_writefd(thread_state->quit_pipe);
381
382 return notify_thread_pipe(write_fd) == 1;
383 }
384
385 struct lttng_thread *launch_application_registration_thread(struct ust_cmd_queue *cmd_queue)
386 {
387 int ret;
388 struct lttng_pipe *quit_pipe;
389 struct thread_state *thread_state = nullptr;
390 struct lttng_thread *thread = nullptr;
391 const bool is_root = (getuid() == 0);
392 int application_socket = -1;
393
394 thread_state = zmalloc<struct thread_state>();
395 if (!thread_state) {
396 goto error_alloc;
397 }
398 quit_pipe = lttng_pipe_open(FD_CLOEXEC);
399 if (!quit_pipe) {
400 goto error;
401 }
402 thread_state->quit_pipe = quit_pipe;
403 thread_state->ust_cmd_queue = cmd_queue;
404 application_socket = create_application_socket();
405 if (application_socket < 0) {
406 goto error;
407 }
408 thread_state->application_socket = application_socket;
409 sem_init(&thread_state->ready, 0, 0);
410
411 thread = lttng_thread_create("UST application registration",
412 thread_application_registration,
413 shutdown_application_registration_thread,
414 cleanup_application_registration_thread,
415 thread_state);
416 if (!thread) {
417 goto error;
418 }
419 /*
420 * The application registration thread now owns the application socket
421 * and the global thread state. The thread state is used to wait for
422 * the thread's status, but its ownership now belongs to the thread.
423 */
424 application_socket = -1;
425 if (!wait_thread_status(thread_state)) {
426 thread_state = nullptr;
427 goto error;
428 }
429
430 /* Notify all applications to register. */
431 ret = notify_ust_apps(1, is_root);
432 if (ret < 0) {
433 ERR("Failed to notify applications or create the wait shared memory.\n"
434 "Execution continues but there might be problems for already\n"
435 "running applications that wishes to register.");
436 }
437
438 return thread;
439 error:
440 lttng_thread_put(thread);
441 cleanup_application_registration_thread(thread_state);
442 if (application_socket >= 0) {
443 if (close(application_socket)) {
444 PERROR("Failed to close application registration socket");
445 }
446 }
447 error_alloc:
448 return nullptr;
449 }
This page took 0.037317 seconds and 4 git commands to generate.