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