2 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
19 #include <sys/resource.h>
21 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <urcu/list.h>
28 #include <urcu/compiler.h>
31 #include <common/defaults.h>
32 #include <common/common.h>
33 #include <common/consumer/consumer.h>
34 #include <common/consumer/consumer-timer.h>
35 #include <common/compat/poll.h>
36 #include <common/sessiond-comm/sessiond-comm.h>
37 #include <common/utils.h>
38 #include <common/compat/getenv.h>
39 #include <common/fd-tracker/utils.h>
41 #include "lttng-relayd.h"
42 #include "health-relayd.h"
44 /* Global health check unix path */
46 char health_unix_sock_path
[PATH_MAX
];
48 int health_quit_pipe
[2] = { -1, -1 };
51 * Check if the thread quit pipe was triggered.
53 * Return 1 if it was triggered else 0;
56 int check_health_quit_pipe(int fd
, uint32_t events
)
58 if (fd
== health_quit_pipe
[0] && (events
& LPOLLIN
)) {
66 * Send data on a unix socket using the liblttsessiondcomm API.
68 * Return lttcomm error code.
70 static int send_unix_sock(int sock
, void *buf
, size_t len
)
72 /* Check valid length */
77 return lttcomm_send_unix_sock(sock
, buf
, len
);
80 static int create_lttng_rundir_with_perm(const char *rundir
)
84 DBG3("Creating LTTng run directory: %s", rundir
);
86 ret
= mkdir(rundir
, S_IRWXU
);
88 if (errno
!= EEXIST
) {
89 ERR("Unable to create %s", rundir
);
94 } else if (ret
== 0) {
95 int is_root
= !getuid();
100 ret
= utils_get_group_id(tracing_group_name
, true, &gid
);
102 /* Default to root group. */
106 ret
= chown(rundir
, 0, gid
);
108 ERR("Unable to set group on %s", rundir
);
115 S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
);
117 ERR("Unable to set permissions on %s", health_unix_sock_path
);
130 int parse_health_env(void)
132 const char *health_path
;
134 health_path
= lttng_secure_getenv(LTTNG_RELAYD_HEALTH_ENV
);
136 strncpy(health_unix_sock_path
, health_path
,
138 health_unix_sock_path
[PATH_MAX
- 1] = '\0';
145 int setup_health_path(void)
147 int is_root
, ret
= 0;
148 const char *home_path
= NULL
;
149 char *rundir
= NULL
, *relayd_path
= NULL
;
151 ret
= parse_health_env();
159 rundir
= strdup(DEFAULT_LTTNG_RUNDIR
);
166 * Create rundir from home path. This will create something like
169 home_path
= utils_get_home_dir();
171 if (home_path
== NULL
) {
172 /* TODO: Add --socket PATH option */
173 ERR("Can't get HOME directory for sockets creation.");
178 ret
= asprintf(&rundir
, DEFAULT_LTTNG_HOME_RUNDIR
, home_path
);
185 ret
= asprintf(&relayd_path
, DEFAULT_RELAYD_PATH
, rundir
);
191 ret
= create_lttng_rundir_with_perm(rundir
);
196 ret
= create_lttng_rundir_with_perm(relayd_path
);
202 if (strlen(health_unix_sock_path
) != 0) {
205 snprintf(health_unix_sock_path
, sizeof(health_unix_sock_path
),
206 DEFAULT_GLOBAL_RELAY_HEALTH_UNIX_SOCK
,
209 /* Set health check Unix path */
210 if (strlen(health_unix_sock_path
) != 0) {
214 snprintf(health_unix_sock_path
, sizeof(health_unix_sock_path
),
215 DEFAULT_HOME_RELAY_HEALTH_UNIX_SOCK
,
216 home_path
, (int) getpid());
226 int accept_unix_socket(void *data
, int *out_fd
)
229 int accepting_sock
= *((int *) data
);
231 ret
= lttcomm_accept_unix_sock(accepting_sock
);
243 int open_unix_socket(void *data
, int *out_fd
)
246 const char *path
= data
;
248 ret
= lttcomm_create_unix_sock(path
);
260 * Thread managing health check socket.
262 void *thread_manage_health(void *data
)
264 int sock
= -1, new_sock
= -1, ret
, i
, pollfd
, err
= -1;
265 uint32_t revents
, nb_fd
;
266 struct lttng_poll_event events
;
267 struct health_comm_msg msg
;
268 struct health_comm_reply reply
;
272 DBG("[thread] Manage health check started");
276 rcu_register_thread();
278 /* We might hit an error path before this is created. */
279 lttng_poll_init(&events
);
281 /* Create unix socket */
282 ret
= asprintf(&sock_name
, "Unix socket @ %s", health_unix_sock_path
);
284 PERROR("Failed to allocate unix socket name");
288 ret
= fd_tracker_open_unsuspendable_fd(the_fd_tracker
, &sock
,
289 (const char **) &sock_name
, 1, open_unix_socket
,
290 health_unix_sock_path
);
293 ERR("Unable to create health check Unix socket");
300 /* lttng health client socket path permissions */
303 ret
= utils_get_group_id(tracing_group_name
, true, &gid
);
305 /* Default to root group. */
309 ret
= chown(health_unix_sock_path
, 0, gid
);
311 ERR("Unable to set group on %s", health_unix_sock_path
);
317 ret
= chmod(health_unix_sock_path
,
318 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
320 ERR("Unable to set permissions on %s", health_unix_sock_path
);
328 * Set the CLOEXEC flag. Return code is useless because either way, the
331 (void) utils_set_fd_cloexec(sock
);
333 ret
= lttcomm_listen_unix_sock(sock
);
338 /* Size is set to 2 for the unix socket and quit pipe. */
339 ret
= fd_tracker_util_poll_create(the_fd_tracker
,
340 "Health management thread epoll", &events
, 2,
343 ERR("Poll set creation failed");
347 ret
= lttng_poll_add(&events
, health_quit_pipe
[0], LPOLLIN
);
352 /* Add the application registration socket */
353 ret
= lttng_poll_add(&events
, sock
, LPOLLIN
| LPOLLPRI
);
358 lttng_relay_notify_ready();
361 char *accepted_socket_name
;
363 DBG("Health check ready");
365 /* Inifinite blocking call, waiting for transmission */
367 ret
= lttng_poll_wait(&events
, -1);
370 * Restart interrupted system call.
372 if (errno
== EINTR
) {
380 for (i
= 0; i
< nb_fd
; i
++) {
381 /* Fetch once the poll data */
382 revents
= LTTNG_POLL_GETEV(&events
, i
);
383 pollfd
= LTTNG_POLL_GETFD(&events
, i
);
385 /* Thread quit pipe has been closed. Killing thread. */
386 ret
= check_health_quit_pipe(pollfd
, revents
);
392 /* Event on the registration socket */
393 if (pollfd
== sock
) {
394 if (revents
& LPOLLIN
) {
396 } else if (revents
& (LPOLLERR
| LPOLLHUP
| LPOLLRDHUP
)) {
397 ERR("Health socket poll error");
400 ERR("Unexpected poll events %u for sock %d", revents
, pollfd
);
406 ret
= asprintf(&accepted_socket_name
, "Socket accepted from unix socket @ %s",
407 health_unix_sock_path
);
409 PERROR("Failed to allocate name of accepted socket from unix socket @ %s",
410 health_unix_sock_path
);
413 ret
= fd_tracker_open_unsuspendable_fd(the_fd_tracker
, &new_sock
,
414 (const char **) &accepted_socket_name
, 1,
415 accept_unix_socket
, &sock
);
416 free(accepted_socket_name
);
422 * Set the CLOEXEC flag. Return code is useless because either way, the
425 (void) utils_set_fd_cloexec(new_sock
);
427 DBG("Receiving data from client for health...");
428 ret
= lttcomm_recv_unix_sock(new_sock
, (void *)&msg
, sizeof(msg
));
430 DBG("Nothing recv() from client... continuing");
431 ret
= fd_tracker_close_unsuspendable_fd(the_fd_tracker
,
432 &new_sock
, 1, fd_tracker_util_close_fd
,
443 LTTNG_ASSERT(msg
.cmd
== HEALTH_CMD_CHECK
);
445 memset(&reply
, 0, sizeof(reply
));
446 for (i
= 0; i
< NR_HEALTH_RELAYD_TYPES
; i
++) {
448 * health_check_state return 0 if thread is in
451 if (!health_check_state(health_relayd
, i
)) {
452 reply
.ret_code
|= 1ULL << i
;
456 DBG2("Health check return value %" PRIx64
, reply
.ret_code
);
458 ret
= send_unix_sock(new_sock
, (void *) &reply
, sizeof(reply
));
460 ERR("Failed to send health data back to client");
463 /* End of transmission */
464 ret
= fd_tracker_close_unsuspendable_fd(the_fd_tracker
,
465 &new_sock
, 1, fd_tracker_util_close_fd
,
474 lttng_relay_stop_threads();
477 ERR("Health error occurred in %s", __func__
);
479 DBG("Health check thread dying");
480 unlink(health_unix_sock_path
);
482 ret
= fd_tracker_close_unsuspendable_fd(the_fd_tracker
, &sock
,
483 1, fd_tracker_util_close_fd
, NULL
);
490 * We do NOT rmdir rundir nor the relayd path because there are
491 * other processes using them.
494 (void) fd_tracker_util_poll_clean(the_fd_tracker
, &events
);
496 rcu_unregister_thread();