Fix: file-descriptor: missing include guards
[lttng-tools.git] / src / bin / lttng-relayd / health-relayd.cpp
CommitLineData
65931c8b 1/*
ab5be9fa 2 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
65931c8b 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
65931c8b 5 *
65931c8b
MD
6 */
7
6c1c0768 8#define _LGPL_SOURCE
28ab034a
JG
9#include "health-relayd.hpp"
10#include "lttng-relayd.hpp"
11
12#include <common/common.hpp>
13#include <common/compat/getenv.hpp>
14#include <common/compat/poll.hpp>
15#include <common/consumer/consumer-timer.hpp>
16#include <common/consumer/consumer.hpp>
17#include <common/defaults.hpp>
18#include <common/fd-tracker/utils.hpp>
19#include <common/sessiond-comm/sessiond-comm.hpp>
20#include <common/utils.hpp>
21
65931c8b
MD
22#include <fcntl.h>
23#include <getopt.h>
24#include <grp.h>
28ab034a 25#include <inttypes.h>
65931c8b 26#include <limits.h>
28ab034a 27#include <poll.h>
65931c8b
MD
28#include <pthread.h>
29#include <signal.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <sys/ipc.h>
28ab034a 34#include <sys/mman.h>
65931c8b
MD
35#include <sys/resource.h>
36#include <sys/shm.h>
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/types.h>
65931c8b 40#include <unistd.h>
65931c8b 41#include <urcu/compiler.h>
28ab034a 42#include <urcu/list.h>
65931c8b
MD
43
44/* Global health check unix path */
28ab034a 45static char health_unix_sock_path[PATH_MAX];
65931c8b 46
794e2e5f 47int health_quit_pipe[2] = { -1, -1 };
65931c8b 48
65931c8b
MD
49/*
50 * Send data on a unix socket using the liblttsessiondcomm API.
51 *
52 * Return lttcomm error code.
53 */
54static int send_unix_sock(int sock, void *buf, size_t len)
55{
56 /* Check valid length */
57 if (len == 0) {
58 return -1;
59 }
60
61 return lttcomm_send_unix_sock(sock, buf, len);
62}
63
64static int create_lttng_rundir_with_perm(const char *rundir)
65{
66 int ret;
67
68 DBG3("Creating LTTng run directory: %s", rundir);
69
70 ret = mkdir(rundir, S_IRWXU);
71 if (ret < 0) {
72 if (errno != EEXIST) {
73 ERR("Unable to create %s", rundir);
74 goto error;
75 } else {
76 ret = 0;
77 }
78 } else if (ret == 0) {
79 int is_root = !getuid();
80
81 if (is_root) {
28ab59d0
JR
82 gid_t gid;
83
84 ret = utils_get_group_id(tracing_group_name, true, &gid);
85 if (ret) {
86 /* Default to root group. */
87 gid = 0;
88 }
89
90 ret = chown(rundir, 0, gid);
65931c8b
MD
91 if (ret < 0) {
92 ERR("Unable to set group on %s", rundir);
93 PERROR("chown");
94 ret = -1;
95 goto error;
96 }
97
98 ret = chmod(rundir,
28ab034a
JG
99 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH |
100 S_IXOTH);
65931c8b 101 if (ret < 0) {
f7b09ec2 102 ERR("Unable to set permissions on %s", rundir);
65931c8b
MD
103 PERROR("chmod");
104 ret = -1;
105 goto error;
106 }
107 }
108 }
109
110error:
111 return ret;
112}
113
cd9adb8b 114static int parse_health_env()
094fe907
MD
115{
116 const char *health_path;
117
e8fa9fb0 118 health_path = lttng_secure_getenv(LTTNG_RELAYD_HEALTH_ENV);
094fe907 119 if (health_path) {
28ab034a 120 strncpy(health_unix_sock_path, health_path, PATH_MAX);
094fe907
MD
121 health_unix_sock_path[PATH_MAX - 1] = '\0';
122 }
123
124 return 0;
125}
126
cd9adb8b 127static int setup_health_path()
65931c8b
MD
128{
129 int is_root, ret = 0;
cd9adb8b
JG
130 const char *home_path = nullptr;
131 char *rundir = nullptr, *relayd_path = nullptr;
65931c8b 132
094fe907
MD
133 ret = parse_health_env();
134 if (ret) {
135 return ret;
136 }
137
65931c8b
MD
138 is_root = !getuid();
139
140 if (is_root) {
c3844e39 141 rundir = strdup(DEFAULT_LTTNG_RUNDIR);
b6ab01aa
MD
142 if (!rundir) {
143 ret = -ENOMEM;
144 goto end;
145 }
65931c8b
MD
146 } else {
147 /*
148 * Create rundir from home path. This will create something like
149 * $HOME/.lttng
150 */
151 home_path = utils_get_home_dir();
152
cd9adb8b 153 if (home_path == nullptr) {
65931c8b
MD
154 /* TODO: Add --socket PATH option */
155 ERR("Can't get HOME directory for sockets creation.");
156 ret = -EPERM;
157 goto end;
158 }
159
c3844e39 160 ret = asprintf(&rundir, DEFAULT_LTTNG_HOME_RUNDIR, home_path);
65931c8b
MD
161 if (ret < 0) {
162 ret = -ENOMEM;
163 goto end;
164 }
165 }
166
c3844e39 167 ret = asprintf(&relayd_path, DEFAULT_RELAYD_PATH, rundir);
65931c8b
MD
168 if (ret < 0) {
169 ret = -ENOMEM;
170 goto end;
171 }
172
c3844e39 173 ret = create_lttng_rundir_with_perm(rundir);
65931c8b
MD
174 if (ret < 0) {
175 goto end;
176 }
177
178 ret = create_lttng_rundir_with_perm(relayd_path);
179 if (ret < 0) {
180 goto end;
181 }
182
183 if (is_root) {
184 if (strlen(health_unix_sock_path) != 0) {
185 goto end;
186 }
28ab034a
JG
187 snprintf(health_unix_sock_path,
188 sizeof(health_unix_sock_path),
189 DEFAULT_GLOBAL_RELAY_HEALTH_UNIX_SOCK,
190 (int) getpid());
65931c8b
MD
191 } else {
192 /* Set health check Unix path */
193 if (strlen(health_unix_sock_path) != 0) {
194 goto end;
195 }
196
28ab034a
JG
197 snprintf(health_unix_sock_path,
198 sizeof(health_unix_sock_path),
199 DEFAULT_HOME_RELAY_HEALTH_UNIX_SOCK,
200 home_path,
201 (int) getpid());
65931c8b
MD
202 }
203
204end:
c3844e39 205 free(rundir);
edd94901 206 free(relayd_path);
65931c8b
MD
207 return ret;
208}
209
28ab034a 210static int accept_unix_socket(void *data, int *out_fd)
1c9bd75b
JG
211{
212 int ret;
213 int accepting_sock = *((int *) data);
214
215 ret = lttcomm_accept_unix_sock(accepting_sock);
216 if (ret < 0) {
217 goto end;
218 }
219
220 *out_fd = ret;
221 ret = 0;
222end:
223 return ret;
224}
225
28ab034a 226static int open_unix_socket(void *data, int *out_fd)
d7eddab9
JG
227{
228 int ret;
ac497a37 229 const char *path = (const char *) data;
d7eddab9
JG
230
231 ret = lttcomm_create_unix_sock(path);
232 if (ret < 0) {
233 goto end;
234 }
235
236 *out_fd = ret;
237 ret = 0;
238end:
239 return ret;
240}
241
65931c8b
MD
242/*
243 * Thread managing health check socket.
244 */
f46376a1 245void *thread_manage_health_relayd(void *data __attribute__((unused)))
65931c8b 246{
8a00688e
MJ
247 int sock = -1, new_sock = -1, ret, i, err = -1;
248 uint32_t nb_fd;
65931c8b
MD
249 struct lttng_poll_event events;
250 struct health_comm_msg msg;
251 struct health_comm_reply reply;
252 int is_root;
d7eddab9 253 char *sock_name;
65931c8b
MD
254
255 DBG("[thread] Manage health check started");
256
257 setup_health_path();
258
259 rcu_register_thread();
260
261 /* We might hit an error path before this is created. */
262 lttng_poll_init(&events);
263
264 /* Create unix socket */
d7eddab9
JG
265 ret = asprintf(&sock_name, "Unix socket @ %s", health_unix_sock_path);
266 if (ret == -1) {
267 PERROR("Failed to allocate unix socket name");
268 err = -1;
269 goto error;
270 }
28ab034a
JG
271 ret = fd_tracker_open_unsuspendable_fd(the_fd_tracker,
272 &sock,
273 (const char **) &sock_name,
274 1,
275 open_unix_socket,
276 health_unix_sock_path);
d7eddab9
JG
277 free(sock_name);
278 if (ret < 0) {
65931c8b 279 ERR("Unable to create health check Unix socket");
7568ddbf 280 err = -1;
65931c8b
MD
281 goto error;
282 }
283
284 is_root = !getuid();
285 if (is_root) {
286 /* lttng health client socket path permissions */
28ab59d0
JR
287 gid_t gid;
288
289 ret = utils_get_group_id(tracing_group_name, true, &gid);
290 if (ret) {
291 /* Default to root group. */
292 gid = 0;
293 }
294
295 ret = chown(health_unix_sock_path, 0, gid);
65931c8b
MD
296 if (ret < 0) {
297 ERR("Unable to set group on %s", health_unix_sock_path);
298 PERROR("chown");
7568ddbf 299 err = -1;
65931c8b
MD
300 goto error;
301 }
302
28ab034a 303 ret = chmod(health_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
65931c8b
MD
304 if (ret < 0) {
305 ERR("Unable to set permissions on %s", health_unix_sock_path);
306 PERROR("chmod");
7568ddbf 307 err = -1;
65931c8b
MD
308 goto error;
309 }
310 }
311
312 /*
313 * Set the CLOEXEC flag. Return code is useless because either way, the
314 * show must go on.
315 */
316 (void) utils_set_fd_cloexec(sock);
317
318 ret = lttcomm_listen_unix_sock(sock);
319 if (ret < 0) {
320 goto error;
321 }
322
aa91fbc5 323 /* Size is set to 2 for the unix socket and quit pipe. */
28ab034a
JG
324 ret = fd_tracker_util_poll_create(
325 the_fd_tracker, "Health management thread epoll", &events, 2, LTTNG_CLOEXEC);
65931c8b
MD
326 if (ret < 0) {
327 ERR("Poll set creation failed");
328 goto error;
329 }
330
331 ret = lttng_poll_add(&events, health_quit_pipe[0], LPOLLIN);
332 if (ret < 0) {
333 goto error;
334 }
335
336 /* Add the application registration socket */
337 ret = lttng_poll_add(&events, sock, LPOLLIN | LPOLLPRI);
338 if (ret < 0) {
339 goto error;
340 }
341
3fd27398
MD
342 lttng_relay_notify_ready();
343
cd9adb8b 344 while (true) {
1c9bd75b
JG
345 char *accepted_socket_name;
346
65931c8b
MD
347 DBG("Health check ready");
348
349 /* Inifinite blocking call, waiting for transmission */
28ab034a 350 restart:
65931c8b
MD
351 ret = lttng_poll_wait(&events, -1);
352 if (ret < 0) {
353 /*
354 * Restart interrupted system call.
355 */
356 if (errno == EINTR) {
357 goto restart;
358 }
359 goto error;
360 }
361
362 nb_fd = ret;
363
364 for (i = 0; i < nb_fd; i++) {
365 /* Fetch once the poll data */
8a00688e
MJ
366 const auto revents = LTTNG_POLL_GETEV(&events, i);
367 const auto pollfd = LTTNG_POLL_GETFD(&events, i);
65931c8b 368
8a00688e
MJ
369 /* Activity on thread quit pipe, exiting. */
370 if (pollfd == health_quit_pipe[0]) {
371 DBG("Activity on thread quit pipe");
65931c8b
MD
372 err = 0;
373 goto exit;
374 }
375
376 /* Event on the registration socket */
377 if (pollfd == sock) {
03e43155
MD
378 if (revents & LPOLLIN) {
379 continue;
380 } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
65931c8b
MD
381 ERR("Health socket poll error");
382 goto error;
03e43155 383 } else {
28ab034a
JG
384 ERR("Unexpected poll events %u for sock %d",
385 revents,
386 pollfd);
03e43155 387 goto error;
65931c8b
MD
388 }
389 }
390 }
391
28ab034a
JG
392 ret = asprintf(&accepted_socket_name,
393 "Socket accepted from unix socket @ %s",
394 health_unix_sock_path);
1c9bd75b
JG
395 if (ret == -1) {
396 PERROR("Failed to allocate name of accepted socket from unix socket @ %s",
28ab034a 397 health_unix_sock_path);
1c9bd75b
JG
398 goto error;
399 }
28ab034a
JG
400 ret = fd_tracker_open_unsuspendable_fd(the_fd_tracker,
401 &new_sock,
402 (const char **) &accepted_socket_name,
403 1,
404 accept_unix_socket,
405 &sock);
1c9bd75b
JG
406 free(accepted_socket_name);
407 if (ret < 0) {
65931c8b
MD
408 goto error;
409 }
410
411 /*
412 * Set the CLOEXEC flag. Return code is useless because either way, the
413 * show must go on.
414 */
415 (void) utils_set_fd_cloexec(new_sock);
416
417 DBG("Receiving data from client for health...");
28ab034a 418 ret = lttcomm_recv_unix_sock(new_sock, (void *) &msg, sizeof(msg));
65931c8b
MD
419 if (ret <= 0) {
420 DBG("Nothing recv() from client... continuing");
28ab034a 421 ret = fd_tracker_close_unsuspendable_fd(
cd9adb8b 422 the_fd_tracker, &new_sock, 1, fd_tracker_util_close_fd, nullptr);
65931c8b
MD
423 if (ret) {
424 PERROR("close");
425 }
426 new_sock = -1;
427 continue;
428 }
429
430 rcu_thread_online();
431
a0377dfe 432 LTTNG_ASSERT(msg.cmd == HEALTH_CMD_CHECK);
65931c8b 433
53efb85a 434 memset(&reply, 0, sizeof(reply));
65931c8b
MD
435 for (i = 0; i < NR_HEALTH_RELAYD_TYPES; i++) {
436 /*
437 * health_check_state return 0 if thread is in
438 * error.
439 */
440 if (!health_check_state(health_relayd, i)) {
441 reply.ret_code |= 1ULL << i;
442 }
443 }
444
445 DBG2("Health check return value %" PRIx64, reply.ret_code);
446
447 ret = send_unix_sock(new_sock, (void *) &reply, sizeof(reply));
448 if (ret < 0) {
449 ERR("Failed to send health data back to client");
450 }
451
452 /* End of transmission */
28ab034a 453 ret = fd_tracker_close_unsuspendable_fd(
cd9adb8b 454 the_fd_tracker, &new_sock, 1, fd_tracker_util_close_fd, nullptr);
65931c8b
MD
455 if (ret) {
456 PERROR("close");
457 }
458 new_sock = -1;
459 }
460
65931c8b 461error:
81714439
JG
462 lttng_relay_stop_threads();
463exit:
65931c8b
MD
464 if (err) {
465 ERR("Health error occurred in %s", __func__);
466 }
467 DBG("Health check thread dying");
468 unlink(health_unix_sock_path);
469 if (sock >= 0) {
28ab034a 470 ret = fd_tracker_close_unsuspendable_fd(
cd9adb8b 471 the_fd_tracker, &sock, 1, fd_tracker_util_close_fd, nullptr);
65931c8b
MD
472 if (ret) {
473 PERROR("close");
474 }
475 }
476
dcbcae3e
MD
477 /*
478 * We do NOT rmdir rundir nor the relayd path because there are
479 * other processes using them.
480 */
481
aa91fbc5 482 (void) fd_tracker_util_poll_clean(the_fd_tracker, &events);
65931c8b
MD
483
484 rcu_unregister_thread();
cd9adb8b 485 return nullptr;
65931c8b 486}
This page took 0.083244 seconds and 4 git commands to generate.