Prepare for '-Wunused-parameter'
[lttng-tools.git] / src / bin / lttng-consumerd / health-consumerd.cpp
CommitLineData
5c635c72 1/*
ab5be9fa 2 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5c635c72 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
5c635c72 5 *
5c635c72
MD
6 */
7
6c1c0768 8#define _LGPL_SOURCE
5c635c72
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>
5c635c72
MD
28#include <urcu/compiler.h>
29#include <ulimit.h>
6c71277b 30#include <inttypes.h>
5c635c72
MD
31
32#include <common/defaults.h>
33#include <common/common.h>
c8fea79c
JR
34#include <common/consumer/consumer.h>
35#include <common/consumer/consumer-timer.h>
5c635c72
MD
36#include <common/compat/poll.h>
37#include <common/sessiond-comm/sessiond-comm.h>
38#include <common/utils.h>
39
40#include "lttng-consumerd.h"
41#include "health-consumerd.h"
42
43/* Global health check unix path */
44static char health_unix_sock_path[PATH_MAX];
45
46int health_quit_pipe[2];
47
48/*
49 * Check if the thread quit pipe was triggered.
50 *
51 * Return 1 if it was triggered else 0;
52 */
53static
54int check_health_quit_pipe(int fd, uint32_t events)
55{
56 if (fd == health_quit_pipe[0] && (events & LPOLLIN)) {
57 return 1;
58 }
59
60 return 0;
61}
62
63/*
64 * Send data on a unix socket using the liblttsessiondcomm API.
65 *
66 * Return lttcomm error code.
67 */
68static int send_unix_sock(int sock, void *buf, size_t len)
69{
70 /* Check valid length */
71 if (len == 0) {
72 return -1;
73 }
74
75 return lttcomm_send_unix_sock(sock, buf, len);
76}
77
78static
79int setup_health_path(void)
80{
81 int is_root, ret = 0;
82 enum lttng_consumer_type type;
83 const char *home_path;
84
85 type = lttng_consumer_get_type();
86 is_root = !getuid();
87
88 if (is_root) {
89 if (strlen(health_unix_sock_path) != 0) {
90 goto end;
91 }
92 switch (type) {
93 case LTTNG_CONSUMER_KERNEL:
94 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
95 DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK);
96 break;
97 case LTTNG_CONSUMER64_UST:
98 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
99 DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK);
100 break;
101 case LTTNG_CONSUMER32_UST:
102 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
103 DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK);
104 break;
105 default:
106 ret = -EINVAL;
107 goto end;
108 }
109 } else {
5c635c72
MD
110 home_path = utils_get_home_dir();
111 if (home_path == NULL) {
112 /* TODO: Add --socket PATH option */
113 ERR("Can't get HOME directory for sockets creation.");
114 ret = -EPERM;
115 goto end;
116 }
117
5c635c72
MD
118 /* Set health check Unix path */
119 if (strlen(health_unix_sock_path) != 0) {
120 goto end;
121 }
122 switch (type) {
123 case LTTNG_CONSUMER_KERNEL:
124 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
dbc8403d 125 DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK, home_path);
5c635c72
MD
126 break;
127 case LTTNG_CONSUMER64_UST:
128 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
dbc8403d 129 DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK, home_path);
5c635c72
MD
130 break;
131 case LTTNG_CONSUMER32_UST:
132 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
dbc8403d 133 DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK, home_path);
5c635c72
MD
134 break;
135 default:
136 ret = -EINVAL;
137 goto end;
138 }
139 }
5c635c72
MD
140end:
141 return ret;
142}
143
144/*
145 * Thread managing health check socket.
146 */
f46376a1 147void *thread_manage_health_consumerd(void *data __attribute__((unused)))
5c635c72
MD
148{
149 int sock = -1, new_sock = -1, ret, i, pollfd, err = -1;
150 uint32_t revents, nb_fd;
151 struct lttng_poll_event events;
152 struct health_comm_msg msg;
153 struct health_comm_reply reply;
6c71277b 154 int is_root;
5c635c72
MD
155
156 DBG("[thread] Manage health check started");
157
158 setup_health_path();
159
160 rcu_register_thread();
161
162 /* We might hit an error path before this is created. */
163 lttng_poll_init(&events);
164
165 /* Create unix socket */
166 sock = lttcomm_create_unix_sock(health_unix_sock_path);
167 if (sock < 0) {
168 ERR("Unable to create health check Unix socket");
67fe4075 169 err = -1;
5c635c72
MD
170 goto error;
171 }
172
6c71277b
MD
173 is_root = !getuid();
174 if (is_root) {
175 /* lttng health client socket path permissions */
28ab59d0
JR
176 gid_t gid;
177
178 ret = utils_get_group_id(tracing_group_name, true, &gid);
179 if (ret) {
180 /* Default to root group. */
181 gid = 0;
182 }
183
184 ret = chown(health_unix_sock_path, 0, gid);
6c71277b
MD
185 if (ret < 0) {
186 ERR("Unable to set group on %s", health_unix_sock_path);
187 PERROR("chown");
67fe4075 188 err = -1;
6c71277b
MD
189 goto error;
190 }
191
192 ret = chmod(health_unix_sock_path,
193 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
194 if (ret < 0) {
195 ERR("Unable to set permissions on %s", health_unix_sock_path);
196 PERROR("chmod");
67fe4075 197 err = -1;
6c71277b
MD
198 goto error;
199 }
200 }
201
5c635c72
MD
202 /*
203 * Set the CLOEXEC flag. Return code is useless because either way, the
204 * show must go on.
205 */
206 (void) utils_set_fd_cloexec(sock);
207
208 ret = lttcomm_listen_unix_sock(sock);
209 if (ret < 0) {
210 goto error;
211 }
212
3069d754 213 /* Size is set to 2 for the quit pipe and registration socket. */
5c635c72
MD
214 ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
215 if (ret < 0) {
216 ERR("Poll set creation failed");
217 goto error;
218 }
219
220 ret = lttng_poll_add(&events, health_quit_pipe[0], LPOLLIN);
221 if (ret < 0) {
222 goto error;
223 }
224
225 /* Add the application registration socket */
226 ret = lttng_poll_add(&events, sock, LPOLLIN | LPOLLPRI);
227 if (ret < 0) {
228 goto error;
229 }
230
748b7b07
MD
231 /* Perform prior memory accesses before decrementing ready */
232 cmm_smp_mb__before_uatomic_dec();
233 uatomic_dec(&lttng_consumer_ready);
234
5c635c72
MD
235 while (1) {
236 DBG("Health check ready");
237
238 /* Inifinite blocking call, waiting for transmission */
239restart:
240 ret = lttng_poll_wait(&events, -1);
241 if (ret < 0) {
242 /*
243 * Restart interrupted system call.
244 */
245 if (errno == EINTR) {
246 goto restart;
247 }
248 goto error;
249 }
250
251 nb_fd = ret;
252
253 for (i = 0; i < nb_fd; i++) {
254 /* Fetch once the poll data */
255 revents = LTTNG_POLL_GETEV(&events, i);
256 pollfd = LTTNG_POLL_GETFD(&events, i);
257
258 /* Thread quit pipe has been closed. Killing thread. */
259 ret = check_health_quit_pipe(pollfd, revents);
260 if (ret) {
261 err = 0;
262 goto exit;
263 }
264
265 /* Event on the registration socket */
266 if (pollfd == sock) {
03e43155
MD
267 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)
268 && !(revents & LPOLLIN)) {
5c635c72
MD
269 ERR("Health socket poll error");
270 goto error;
271 }
272 }
273 }
274
275 new_sock = lttcomm_accept_unix_sock(sock);
276 if (new_sock < 0) {
277 goto error;
278 }
279
280 /*
281 * Set the CLOEXEC flag. Return code is useless because either way, the
282 * show must go on.
283 */
284 (void) utils_set_fd_cloexec(new_sock);
285
286 DBG("Receiving data from client for health...");
287 ret = lttcomm_recv_unix_sock(new_sock, (void *)&msg, sizeof(msg));
288 if (ret <= 0) {
289 DBG("Nothing recv() from client... continuing");
290 ret = close(new_sock);
291 if (ret) {
292 PERROR("close");
293 }
294 new_sock = -1;
295 continue;
296 }
297
298 rcu_thread_online();
299
a0377dfe 300 LTTNG_ASSERT(msg.cmd == HEALTH_CMD_CHECK);
5c635c72 301
53efb85a 302 memset(&reply, 0, sizeof(reply));
6c71277b
MD
303 for (i = 0; i < NR_HEALTH_CONSUMERD_TYPES; i++) {
304 /*
305 * health_check_state return 0 if thread is in
306 * error.
307 */
308 if (!health_check_state(health_consumerd, i)) {
309 reply.ret_code |= 1ULL << i;
310 }
5c635c72
MD
311 }
312
6137f630 313 DBG("Health check return value %" PRIx64, reply.ret_code);
5c635c72
MD
314
315 ret = send_unix_sock(new_sock, (void *) &reply, sizeof(reply));
316 if (ret < 0) {
317 ERR("Failed to send health data back to client");
318 }
319
320 /* End of transmission */
321 ret = close(new_sock);
322 if (ret) {
323 PERROR("close");
324 }
325 new_sock = -1;
326 }
327
328exit:
329error:
330 if (err) {
331 ERR("Health error occurred in %s", __func__);
332 }
333 DBG("Health check thread dying");
334 unlink(health_unix_sock_path);
335 if (sock >= 0) {
336 ret = close(sock);
337 if (ret) {
338 PERROR("close");
339 }
340 }
341
342 lttng_poll_clean(&events);
343
344 rcu_unregister_thread();
345 return NULL;
346}
This page took 0.062826 seconds and 4 git commands to generate.