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>
32 #include <common/defaults.hpp>
33 #include <common/common.hpp>
34 #include <common/consumer/consumer.hpp>
35 #include <common/consumer/consumer-timer.hpp>
36 #include <common/compat/poll.hpp>
37 #include <common/sessiond-comm/sessiond-comm.hpp>
38 #include <common/utils.hpp>
40 #include "lttng-consumerd.hpp"
41 #include "health-consumerd.hpp"
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
);
64 int setup_health_path(void)
67 enum lttng_consumer_type type
;
68 const char *home_path
;
70 type
= lttng_consumer_get_type();
74 if (strlen(health_unix_sock_path
) != 0) {
78 case LTTNG_CONSUMER_KERNEL
:
79 snprintf(health_unix_sock_path
, sizeof(health_unix_sock_path
),
80 DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK
);
82 case LTTNG_CONSUMER64_UST
:
83 snprintf(health_unix_sock_path
, sizeof(health_unix_sock_path
),
84 DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK
);
86 case LTTNG_CONSUMER32_UST
:
87 snprintf(health_unix_sock_path
, sizeof(health_unix_sock_path
),
88 DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK
);
95 home_path
= utils_get_home_dir();
96 if (home_path
== NULL
) {
97 /* TODO: Add --socket PATH option */
98 ERR("Can't get HOME directory for sockets creation.");
103 /* Set health check Unix path */
104 if (strlen(health_unix_sock_path
) != 0) {
108 case LTTNG_CONSUMER_KERNEL
:
109 snprintf(health_unix_sock_path
, sizeof(health_unix_sock_path
),
110 DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK
, home_path
);
112 case LTTNG_CONSUMER64_UST
:
113 snprintf(health_unix_sock_path
, sizeof(health_unix_sock_path
),
114 DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK
, home_path
);
116 case LTTNG_CONSUMER32_UST
:
117 snprintf(health_unix_sock_path
, sizeof(health_unix_sock_path
),
118 DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK
, home_path
);
130 * Thread managing health check socket.
132 void *thread_manage_health_consumerd(void *data
__attribute__((unused
)))
134 int sock
= -1, new_sock
= -1, ret
, i
, err
= -1;
136 struct lttng_poll_event events
;
137 struct health_comm_msg msg
;
138 struct health_comm_reply reply
;
141 DBG("[thread] Manage health check started");
145 rcu_register_thread();
147 /* We might hit an error path before this is created. */
148 lttng_poll_init(&events
);
150 /* Create unix socket */
151 sock
= lttcomm_create_unix_sock(health_unix_sock_path
);
153 ERR("Unable to create health check Unix socket");
160 /* lttng health client socket path permissions */
163 ret
= utils_get_group_id(tracing_group_name
, true, &gid
);
165 /* Default to root group. */
169 ret
= chown(health_unix_sock_path
, 0, gid
);
171 ERR("Unable to set group on %s", health_unix_sock_path
);
177 ret
= chmod(health_unix_sock_path
,
178 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
180 ERR("Unable to set permissions on %s", health_unix_sock_path
);
188 * Set the CLOEXEC flag. Return code is useless because either way, the
191 (void) utils_set_fd_cloexec(sock
);
193 ret
= lttcomm_listen_unix_sock(sock
);
198 /* Size is set to 2 for the quit pipe and registration socket. */
199 ret
= lttng_poll_create(&events
, 2, LTTNG_CLOEXEC
);
201 ERR("Poll set creation failed");
205 ret
= lttng_poll_add(&events
, health_quit_pipe
[0], LPOLLIN
);
210 /* Add the application registration socket */
211 ret
= lttng_poll_add(&events
, sock
, LPOLLIN
| LPOLLPRI
);
216 /* Perform prior memory accesses before decrementing ready */
217 cmm_smp_mb__before_uatomic_dec();
218 uatomic_dec(<tng_consumer_ready
);
221 DBG("Health check ready");
223 /* Inifinite blocking call, waiting for transmission */
225 ret
= lttng_poll_wait(&events
, -1);
228 * Restart interrupted system call.
230 if (errno
== EINTR
) {
238 for (i
= 0; i
< nb_fd
; i
++) {
239 /* Fetch once the poll data */
240 const auto revents
= LTTNG_POLL_GETEV(&events
, i
);
241 const auto pollfd
= LTTNG_POLL_GETFD(&events
, i
);
243 /* Activity on health quit pipe, exiting. */
244 if (pollfd
== health_quit_pipe
[0]) {
245 DBG("Activity on health quit pipe");
250 /* Event on the registration socket */
251 if (pollfd
== sock
) {
252 if (revents
& (LPOLLERR
| LPOLLHUP
| LPOLLRDHUP
)
253 && !(revents
& LPOLLIN
)) {
254 ERR("Health socket poll error");
260 new_sock
= lttcomm_accept_unix_sock(sock
);
266 * Set the CLOEXEC flag. Return code is useless because either way, the
269 (void) utils_set_fd_cloexec(new_sock
);
271 DBG("Receiving data from client for health...");
272 ret
= lttcomm_recv_unix_sock(new_sock
, (void *)&msg
, sizeof(msg
));
274 DBG("Nothing recv() from client... continuing");
275 ret
= close(new_sock
);
285 LTTNG_ASSERT(msg
.cmd
== HEALTH_CMD_CHECK
);
287 memset(&reply
, 0, sizeof(reply
));
288 for (i
= 0; i
< NR_HEALTH_CONSUMERD_TYPES
; i
++) {
290 * health_check_state return 0 if thread is in
293 if (!health_check_state(health_consumerd
, i
)) {
294 reply
.ret_code
|= 1ULL << i
;
298 DBG("Health check return value %" PRIx64
, reply
.ret_code
);
300 ret
= send_unix_sock(new_sock
, (void *) &reply
, sizeof(reply
));
302 ERR("Failed to send health data back to client");
305 /* End of transmission */
306 ret
= close(new_sock
);
316 ERR("Health error occurred in %s", __func__
);
318 DBG("Health check thread dying");
319 unlink(health_unix_sock_path
);
327 lttng_poll_clean(&events
);
329 rcu_unregister_thread();