2 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
9 #include "health-consumerd.hpp"
10 #include "lttng-consumerd.hpp"
12 #include <common/common.hpp>
13 #include <common/compat/poll.hpp>
14 #include <common/consumer/consumer-timer.hpp>
15 #include <common/consumer/consumer.hpp>
16 #include <common/defaults.hpp>
17 #include <common/sessiond-comm/sessiond-comm.hpp>
18 #include <common/utils.hpp>
33 #include <sys/resource.h>
35 #include <sys/socket.h>
37 #include <sys/types.h>
40 #include <urcu/compiler.h>
41 #include <urcu/list.h>
43 /* Global health check unix path */
44 static char health_unix_sock_path
[PATH_MAX
];
46 int health_quit_pipe
[2] = { -1, -1 };
49 * Send data on a unix socket using the liblttsessiondcomm API.
51 * Return lttcomm error code.
53 static int send_unix_sock(int sock
, void *buf
, size_t len
)
55 /* Check valid length */
60 return lttcomm_send_unix_sock(sock
, buf
, len
);
63 static int setup_health_path()
66 enum lttng_consumer_type type
;
67 const char *home_path
;
69 type
= lttng_consumer_get_type();
73 if (strlen(health_unix_sock_path
) != 0) {
77 case LTTNG_CONSUMER_KERNEL
:
78 snprintf(health_unix_sock_path
,
79 sizeof(health_unix_sock_path
),
80 DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK
);
82 case LTTNG_CONSUMER64_UST
:
83 snprintf(health_unix_sock_path
,
84 sizeof(health_unix_sock_path
),
85 DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK
);
87 case LTTNG_CONSUMER32_UST
:
88 snprintf(health_unix_sock_path
,
89 sizeof(health_unix_sock_path
),
90 DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK
);
97 home_path
= utils_get_home_dir();
98 if (home_path
== nullptr) {
99 /* TODO: Add --socket PATH option */
100 ERR("Can't get HOME directory for sockets creation.");
105 /* Set health check Unix path */
106 if (strlen(health_unix_sock_path
) != 0) {
110 case LTTNG_CONSUMER_KERNEL
:
111 snprintf(health_unix_sock_path
,
112 sizeof(health_unix_sock_path
),
113 DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK
,
116 case LTTNG_CONSUMER64_UST
:
117 snprintf(health_unix_sock_path
,
118 sizeof(health_unix_sock_path
),
119 DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK
,
122 case LTTNG_CONSUMER32_UST
:
123 snprintf(health_unix_sock_path
,
124 sizeof(health_unix_sock_path
),
125 DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK
,
138 * Thread managing health check socket.
140 void *thread_manage_health_consumerd(void *data
__attribute__((unused
)))
142 int sock
= -1, new_sock
= -1, ret
, i
, err
= -1;
144 struct lttng_poll_event events
;
145 struct health_comm_msg msg
;
146 struct health_comm_reply reply
;
149 DBG("[thread] Manage health check started");
153 rcu_register_thread();
155 /* We might hit an error path before this is created. */
156 lttng_poll_init(&events
);
158 /* Create unix socket */
159 sock
= lttcomm_create_unix_sock(health_unix_sock_path
);
161 ERR("Unable to create health check Unix socket");
168 /* lttng health client socket path permissions */
171 ret
= utils_get_group_id(tracing_group_name
, true, &gid
);
173 /* Default to root group. */
177 ret
= chown(health_unix_sock_path
, 0, gid
);
179 ERR("Unable to set group on %s", health_unix_sock_path
);
185 ret
= chmod(health_unix_sock_path
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
187 ERR("Unable to set permissions on %s", health_unix_sock_path
);
195 * Set the CLOEXEC flag. Return code is useless because either way, the
198 (void) utils_set_fd_cloexec(sock
);
200 ret
= lttcomm_listen_unix_sock(sock
);
205 /* Size is set to 2 for the quit pipe and registration socket. */
206 ret
= lttng_poll_create(&events
, 2, LTTNG_CLOEXEC
);
208 ERR("Poll set creation failed");
212 ret
= lttng_poll_add(&events
, health_quit_pipe
[0], LPOLLIN
);
217 /* Add the application registration socket */
218 ret
= lttng_poll_add(&events
, sock
, LPOLLIN
| LPOLLPRI
);
223 /* Perform prior memory accesses before decrementing ready */
224 cmm_smp_mb__before_uatomic_dec();
225 uatomic_dec(<tng_consumer_ready
);
228 DBG("Health check ready");
230 /* Inifinite blocking call, waiting for transmission */
232 ret
= lttng_poll_wait(&events
, -1);
235 * Restart interrupted system call.
237 if (errno
== EINTR
) {
245 for (i
= 0; i
< nb_fd
; i
++) {
246 /* Fetch once the poll data */
247 const auto revents
= LTTNG_POLL_GETEV(&events
, i
);
248 const auto pollfd
= LTTNG_POLL_GETFD(&events
, i
);
250 /* Activity on health quit pipe, exiting. */
251 if (pollfd
== health_quit_pipe
[0]) {
252 DBG("Activity on health quit pipe");
257 /* Event on the registration socket */
258 if (pollfd
== sock
) {
259 if (revents
& (LPOLLERR
| LPOLLHUP
| LPOLLRDHUP
) &&
260 !(revents
& LPOLLIN
)) {
261 ERR("Health socket poll error");
267 new_sock
= lttcomm_accept_unix_sock(sock
);
273 * Set the CLOEXEC flag. Return code is useless because either way, the
276 (void) utils_set_fd_cloexec(new_sock
);
278 DBG("Receiving data from client for health...");
279 ret
= lttcomm_recv_unix_sock(new_sock
, (void *) &msg
, sizeof(msg
));
281 DBG("Nothing recv() from client... continuing");
282 ret
= close(new_sock
);
292 LTTNG_ASSERT(msg
.cmd
== HEALTH_CMD_CHECK
);
294 memset(&reply
, 0, sizeof(reply
));
295 for (i
= 0; i
< NR_HEALTH_CONSUMERD_TYPES
; i
++) {
297 * health_check_state return 0 if thread is in
300 if (!health_check_state(health_consumerd
, i
)) {
301 reply
.ret_code
|= 1ULL << i
;
305 DBG("Health check return value %" PRIx64
, reply
.ret_code
);
307 ret
= send_unix_sock(new_sock
, (void *) &reply
, sizeof(reply
));
309 ERR("Failed to send health data back to client");
312 /* End of transmission */
313 ret
= close(new_sock
);
323 ERR("Health error occurred in %s", __func__
);
325 DBG("Health check thread dying");
326 unlink(health_unix_sock_path
);
334 lttng_poll_clean(&events
);
336 rcu_unregister_thread();