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