2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
3 * Copyright (C) 2018 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License, version 2 only, as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51
16 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "lttng-sessiond.h"
20 #include "health-sessiond.h"
21 #include <common/macros.h>
22 #include <common/error.h>
23 #include <common/utils.h>
24 #include <common/pipe.h>
30 static void cleanup_health_management_thread(void *thread_data
)
32 struct lttng_pipe
*quit_pipe
= thread_data
;
34 lttng_pipe_destroy(quit_pipe
);
38 * Thread managing health check socket.
40 static void *thread_manage_health(void *thread_data
)
42 const bool is_root
= (getuid() == 0);
43 int sock
= -1, new_sock
= -1, ret
, i
, pollfd
, err
= -1;
44 uint32_t revents
, nb_fd
;
45 struct lttng_poll_event events
;
46 struct health_comm_msg msg
;
47 struct health_comm_reply reply
;
48 /* Thread-specific quit pipe. */
49 struct lttng_pipe
*quit_pipe
= thread_data
;
50 const int quit_pipe_read_fd
= lttng_pipe_get_readfd(quit_pipe
);
52 DBG("[thread] Manage health check started");
54 rcu_register_thread();
57 * Created with a size of two for:
61 ret
= lttng_poll_create(&events
, 2, LTTNG_CLOEXEC
);
66 /* Create unix socket */
67 sock
= lttcomm_create_unix_sock(config
.health_unix_sock_path
.value
);
69 ERR("Unable to create health check Unix socket");
74 /* lttng health client socket path permissions */
75 ret
= chown(config
.health_unix_sock_path
.value
, 0,
76 utils_get_group_id(config
.tracing_group_name
.value
));
78 ERR("Unable to set group on %s", config
.health_unix_sock_path
.value
);
83 ret
= chmod(config
.health_unix_sock_path
.value
,
84 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
86 ERR("Unable to set permissions on %s", config
.health_unix_sock_path
.value
);
93 * Set the CLOEXEC flag. Return code is useless because either way, the
96 (void) utils_set_fd_cloexec(sock
);
98 ret
= lttcomm_listen_unix_sock(sock
);
103 ret
= lttng_poll_add(&events
, quit_pipe_read_fd
, LPOLLIN
| LPOLLERR
);
108 /* Add the application registration socket */
109 ret
= lttng_poll_add(&events
, sock
, LPOLLIN
| LPOLLPRI
);
114 sessiond_notify_ready();
117 DBG("Health check ready");
119 /* Infinite blocking call, waiting for transmission */
121 ret
= lttng_poll_wait(&events
, -1);
124 * Restart interrupted system call.
126 if (errno
== EINTR
) {
134 for (i
= 0; i
< nb_fd
; i
++) {
135 /* Fetch once the poll data */
136 revents
= LTTNG_POLL_GETEV(&events
, i
);
137 pollfd
= LTTNG_POLL_GETFD(&events
, i
);
140 /* No activity for this FD (poll implementation). */
144 /* Event on the registration socket */
145 if (pollfd
== sock
) {
146 if (revents
& LPOLLIN
) {
148 } else if (revents
& (LPOLLERR
| LPOLLHUP
| LPOLLRDHUP
)) {
149 ERR("Health socket poll error");
152 ERR("Unexpected poll events %u for sock %d", revents
, pollfd
);
156 /* Event on the thread's quit pipe. */
162 new_sock
= lttcomm_accept_unix_sock(sock
);
168 * Set the CLOEXEC flag. Return code is useless because either way, the
171 (void) utils_set_fd_cloexec(new_sock
);
173 DBG("Receiving data from client for health...");
174 ret
= lttcomm_recv_unix_sock(new_sock
, (void *)&msg
, sizeof(msg
));
176 DBG("Nothing recv() from client... continuing");
177 ret
= close(new_sock
);
186 memset(&reply
, 0, sizeof(reply
));
187 for (i
= 0; i
< NR_HEALTH_SESSIOND_TYPES
; i
++) {
189 * health_check_state returns 0 if health is
192 if (!health_check_state(health_sessiond
, i
)) {
193 reply
.ret_code
|= 1ULL << i
;
197 DBG2("Health check return value %" PRIx64
, reply
.ret_code
);
199 ret
= lttcomm_send_unix_sock(new_sock
, (void *) &reply
,
202 ERR("Failed to send health data back to client");
205 /* End of transmission */
206 ret
= close(new_sock
);
215 ERR("Health error occurred in %s", __func__
);
217 DBG("Health check thread dying");
218 unlink(config
.health_unix_sock_path
.value
);
226 lttng_poll_clean(&events
);
227 rcu_unregister_thread();
231 static bool shutdown_health_management_thread(void *thread_data
)
235 struct lttng_pipe
*health_quit_pipe
= thread_data
;
237 pipe_write_fd
= lttng_pipe_get_writefd(health_quit_pipe
);
238 ret
= notify_thread_pipe(pipe_write_fd
);
240 ERR("Failed to notify Health management thread's quit pipe");
248 bool launch_health_management_thread(void)
250 struct lttng_thread
*thread
;
251 struct lttng_pipe
*health_quit_pipe
= NULL
;
253 health_quit_pipe
= lttng_pipe_open(FD_CLOEXEC
);
254 if (!health_quit_pipe
) {
258 thread
= lttng_thread_create("Health management",
259 thread_manage_health
,
260 shutdown_health_management_thread
,
261 cleanup_health_management_thread
,
266 lttng_thread_put(thread
);
269 cleanup_health_management_thread(health_quit_pipe
);