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