SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / src / bin / lttng-sessiond / notification-thread.c
CommitLineData
ab0ee2ca 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
ab0ee2ca 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
ab0ee2ca 5 *
ab0ee2ca
JG
6 */
7
8#define _LGPL_SOURCE
9#include <lttng/trigger/trigger.h>
10#include <lttng/notification/channel-internal.h>
11#include <lttng/notification/notification-internal.h>
12#include <lttng/condition/condition-internal.h>
13#include <lttng/condition/buffer-usage-internal.h>
14#include <common/error.h>
15#include <common/config/session-config.h>
16#include <common/defaults.h>
17#include <common/utils.h>
ab0ee2ca
JG
18#include <common/align.h>
19#include <common/time.h>
20#include <sys/eventfd.h>
21#include <sys/stat.h>
22#include <time.h>
23#include <signal.h>
24
25#include "notification-thread.h"
26#include "notification-thread-events.h"
27#include "notification-thread-commands.h"
28#include "lttng-sessiond.h"
29#include "health-sessiond.h"
c8a9de5a 30#include "thread.h"
ab0ee2ca 31
1831ae68
FD
32#include "kernel.h"
33#include <common/kernel-ctl/kernel-ctl.h>
34
ab0ee2ca
JG
35#include <urcu.h>
36#include <urcu/list.h>
37#include <urcu/rculfhash.h>
38
ab0ee2ca
JG
39/*
40 * Destroy the thread data previously created by the init function.
41 */
42void notification_thread_handle_destroy(
43 struct notification_thread_handle *handle)
44{
45 int ret;
ab0ee2ca
JG
46
47 if (!handle) {
48 goto end;
49 }
50
8ada111f 51 assert(cds_list_empty(&handle->cmd_queue.list));
ab0ee2ca 52 pthread_mutex_destroy(&handle->cmd_queue.lock);
c8a9de5a 53 sem_destroy(&handle->ready);
ab0ee2ca 54
814b4934
JR
55 if (handle->cmd_queue.event_pipe) {
56 lttng_pipe_destroy(handle->cmd_queue.event_pipe);
57 }
ab0ee2ca
JG
58 if (handle->channel_monitoring_pipes.ust32_consumer >= 0) {
59 ret = close(handle->channel_monitoring_pipes.ust32_consumer);
60 if (ret) {
61 PERROR("close 32-bit consumer channel monitoring pipe");
62 }
63 }
64 if (handle->channel_monitoring_pipes.ust64_consumer >= 0) {
65 ret = close(handle->channel_monitoring_pipes.ust64_consumer);
66 if (ret) {
67 PERROR("close 64-bit consumer channel monitoring pipe");
68 }
69 }
70 if (handle->channel_monitoring_pipes.kernel_consumer >= 0) {
71 ret = close(handle->channel_monitoring_pipes.kernel_consumer);
72 if (ret) {
73 PERROR("close kernel consumer channel monitoring pipe");
74 }
75 }
1831ae68
FD
76
77 /* TODO: refactor this if needed. Lifetime of the kernel notification
78 * event source.
79 * event_trigger_sources.kernel_tracer is owned by the main thread and
80 * is closed at this point.
81 */
82 handle->event_trigger_sources.kernel_tracer = -1;
ab0ee2ca
JG
83end:
84 free(handle);
85}
86
1831ae68
FD
87/*
88 * TODO: refactor this if needed. Lifetime of the kernel notification event source.
89 * The kernel_notification_monitor_fd ownwership remain to the main thread.
90 * This is because we need to close this fd before removing the modules.
91 */
ab0ee2ca
JG
92struct notification_thread_handle *notification_thread_handle_create(
93 struct lttng_pipe *ust32_channel_monitor_pipe,
94 struct lttng_pipe *ust64_channel_monitor_pipe,
1831ae68
FD
95 struct lttng_pipe *kernel_channel_monitor_pipe,
96 int kernel_notification_monitor_fd)
ab0ee2ca
JG
97{
98 int ret;
99 struct notification_thread_handle *handle;
814b4934 100 struct lttng_pipe *event_pipe = NULL;
ab0ee2ca
JG
101
102 handle = zmalloc(sizeof(*handle));
103 if (!handle) {
104 goto end;
105 }
106
1831ae68
FD
107 handle->event_trigger_sources.kernel_tracer = -1;
108
c8a9de5a
JG
109 sem_init(&handle->ready, 0, 0);
110
18d08850 111 event_pipe = lttng_pipe_open(FD_CLOEXEC);
814b4934
JR
112 if (!event_pipe) {
113 ERR("event_pipe creation");
ab0ee2ca
JG
114 goto error;
115 }
814b4934
JR
116
117 handle->cmd_queue.event_pipe = event_pipe;
118 event_pipe = NULL;
119
ab0ee2ca
JG
120 CDS_INIT_LIST_HEAD(&handle->cmd_queue.list);
121 ret = pthread_mutex_init(&handle->cmd_queue.lock, NULL);
122 if (ret) {
123 goto error;
124 }
125
126 if (ust32_channel_monitor_pipe) {
127 handle->channel_monitoring_pipes.ust32_consumer =
128 lttng_pipe_release_readfd(
129 ust32_channel_monitor_pipe);
130 if (handle->channel_monitoring_pipes.ust32_consumer < 0) {
131 goto error;
132 }
133 } else {
134 handle->channel_monitoring_pipes.ust32_consumer = -1;
135 }
136 if (ust64_channel_monitor_pipe) {
137 handle->channel_monitoring_pipes.ust64_consumer =
138 lttng_pipe_release_readfd(
139 ust64_channel_monitor_pipe);
140 if (handle->channel_monitoring_pipes.ust64_consumer < 0) {
141 goto error;
142 }
143 } else {
144 handle->channel_monitoring_pipes.ust64_consumer = -1;
145 }
146 if (kernel_channel_monitor_pipe) {
147 handle->channel_monitoring_pipes.kernel_consumer =
148 lttng_pipe_release_readfd(
149 kernel_channel_monitor_pipe);
150 if (handle->channel_monitoring_pipes.kernel_consumer < 0) {
151 goto error;
152 }
153 } else {
154 handle->channel_monitoring_pipes.kernel_consumer = -1;
155 }
1831ae68
FD
156
157 handle->event_trigger_sources.kernel_tracer = kernel_notification_monitor_fd;
158
159 CDS_INIT_LIST_HEAD(&handle->event_trigger_sources.list);
160 ret = pthread_mutex_init(&handle->event_trigger_sources.lock, NULL);
161 if (ret) {
162 goto error;
163 }
ab0ee2ca
JG
164end:
165 return handle;
166error:
814b4934 167 lttng_pipe_destroy(event_pipe);
ab0ee2ca
JG
168 notification_thread_handle_destroy(handle);
169 return NULL;
170}
171
172static
173char *get_notification_channel_sock_path(void)
174{
175 int ret;
176 bool is_root = !getuid();
177 char *sock_path;
178
179 sock_path = zmalloc(LTTNG_PATH_MAX);
180 if (!sock_path) {
181 goto error;
182 }
183
184 if (is_root) {
185 ret = snprintf(sock_path, LTTNG_PATH_MAX,
186 DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK);
187 if (ret < 0) {
188 goto error;
189 }
190 } else {
4f00620d 191 const char *home_path = utils_get_home_dir();
ab0ee2ca
JG
192
193 if (!home_path) {
194 ERR("Can't get HOME directory for socket creation");
195 goto error;
196 }
197
198 ret = snprintf(sock_path, LTTNG_PATH_MAX,
199 DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK,
200 home_path);
201 if (ret < 0) {
202 goto error;
203 }
204 }
205
206 return sock_path;
207error:
208 free(sock_path);
209 return NULL;
210}
211
212static
213void notification_channel_socket_destroy(int fd)
214{
215 int ret;
216 char *sock_path = get_notification_channel_sock_path();
217
218 DBG("[notification-thread] Destroying notification channel socket");
219
220 if (sock_path) {
221 ret = unlink(sock_path);
222 free(sock_path);
223 if (ret < 0) {
224 PERROR("unlink notification channel socket");
225 }
226 }
227
228 ret = close(fd);
229 if (ret) {
230 PERROR("close notification channel socket");
231 }
232}
233
234static
235int notification_channel_socket_create(void)
236{
237 int fd = -1, ret;
238 char *sock_path = get_notification_channel_sock_path();
239
240 DBG("[notification-thread] Creating notification channel UNIX socket at %s",
241 sock_path);
242
243 ret = lttcomm_create_unix_sock(sock_path);
244 if (ret < 0) {
245 ERR("[notification-thread] Failed to create notification socket");
246 goto error;
247 }
248 fd = ret;
249
250 ret = chmod(sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
251 if (ret < 0) {
252 ERR("Set file permissions failed: %s", sock_path);
253 PERROR("chmod notification channel socket");
254 goto error;
255 }
256
257 if (getuid() == 0) {
28ab59d0
JR
258 gid_t gid;
259
260 ret = utils_get_group_id(config.tracing_group_name.value, true,
261 &gid);
262 if (ret) {
263 /* Default to root group. */
264 gid = 0;
265 }
266
267 ret = chown(sock_path, 0, gid);
ab0ee2ca
JG
268 if (ret) {
269 ERR("Failed to set the notification channel socket's group");
270 ret = -1;
271 goto error;
272 }
273 }
274
275 DBG("[notification-thread] Notification channel UNIX socket created (fd = %i)",
276 fd);
277 free(sock_path);
278 return fd;
279error:
280 if (fd >= 0 && close(fd) < 0) {
281 PERROR("close notification channel socket");
282 }
283 free(sock_path);
284 return ret;
285}
286
287static
288int init_poll_set(struct lttng_poll_event *poll_set,
289 struct notification_thread_handle *handle,
290 int notification_channel_socket)
291{
292 int ret;
293
294 /*
1831ae68 295 * Create pollset with size 6:
ab0ee2ca
JG
296 * - notification channel socket (listen for new connections),
297 * - command queue event fd (internal sessiond commands),
298 * - consumerd (32-bit user space) channel monitor pipe,
299 * - consumerd (64-bit user space) channel monitor pipe,
300 * - consumerd (kernel) channel monitor pipe.
1831ae68 301 * - kernel trigger event pipe,
ab0ee2ca 302 */
1831ae68 303 ret = lttng_poll_create(poll_set, 6, LTTNG_CLOEXEC);
ab0ee2ca
JG
304 if (ret < 0) {
305 goto end;
306 }
307
308 ret = lttng_poll_add(poll_set, notification_channel_socket,
309 LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP);
310 if (ret < 0) {
311 ERR("[notification-thread] Failed to add notification channel socket to pollset");
312 goto error;
313 }
814b4934 314 ret = lttng_poll_add(poll_set, lttng_pipe_get_readfd(handle->cmd_queue.event_pipe),
ab0ee2ca
JG
315 LPOLLIN | LPOLLERR);
316 if (ret < 0) {
317 ERR("[notification-thread] Failed to add notification command queue event fd to pollset");
318 goto error;
319 }
320 ret = lttng_poll_add(poll_set,
321 handle->channel_monitoring_pipes.ust32_consumer,
322 LPOLLIN | LPOLLERR);
323 if (ret < 0) {
324 ERR("[notification-thread] Failed to add ust-32 channel monitoring pipe fd to pollset");
325 goto error;
326 }
327 ret = lttng_poll_add(poll_set,
328 handle->channel_monitoring_pipes.ust64_consumer,
329 LPOLLIN | LPOLLERR);
330 if (ret < 0) {
331 ERR("[notification-thread] Failed to add ust-64 channel monitoring pipe fd to pollset");
332 goto error;
333 }
334 if (handle->channel_monitoring_pipes.kernel_consumer < 0) {
1831ae68 335 goto skip_kernel_consumer;
ab0ee2ca
JG
336 }
337 ret = lttng_poll_add(poll_set,
338 handle->channel_monitoring_pipes.kernel_consumer,
339 LPOLLIN | LPOLLERR);
340 if (ret < 0) {
341 ERR("[notification-thread] Failed to add kernel channel monitoring pipe fd to pollset");
342 goto error;
343 }
1831ae68
FD
344
345skip_kernel_consumer:
346 if (handle->event_trigger_sources.kernel_tracer < 0) {
347 goto end;
348 }
349
350 ret = lttng_poll_add(poll_set,
351 handle->event_trigger_sources.kernel_tracer,
352 LPOLLIN | LPOLLERR);
353 if (ret < 0) {
354 ERR("[notification-thread] Failed to add kernel trigger notification monitoring pipe fd to pollset");
355 goto error;
356 }
ab0ee2ca
JG
357end:
358 return ret;
359error:
360 lttng_poll_clean(poll_set);
361 return ret;
362}
363
364static
365void fini_thread_state(struct notification_thread_state *state)
366{
367 int ret;
368
369 if (state->client_socket_ht) {
370 ret = handle_notification_thread_client_disconnect_all(state);
371 assert(!ret);
372 ret = cds_lfht_destroy(state->client_socket_ht, NULL);
373 assert(!ret);
374 }
1831ae68
FD
375 if (state->client_id_ht) {
376 ret = cds_lfht_destroy(state->client_id_ht, NULL);
377 assert(!ret);
378 }
ab0ee2ca
JG
379 if (state->triggers_ht) {
380 ret = handle_notification_thread_trigger_unregister_all(state);
381 assert(!ret);
382 ret = cds_lfht_destroy(state->triggers_ht, NULL);
383 assert(!ret);
384 }
385 if (state->channel_triggers_ht) {
386 ret = cds_lfht_destroy(state->channel_triggers_ht, NULL);
387 assert(!ret);
388 }
389 if (state->channel_state_ht) {
390 ret = cds_lfht_destroy(state->channel_state_ht, NULL);
391 assert(!ret);
392 }
393 if (state->notification_trigger_clients_ht) {
394 ret = cds_lfht_destroy(state->notification_trigger_clients_ht,
395 NULL);
396 assert(!ret);
397 }
398 if (state->channels_ht) {
8abe313a
JG
399 ret = cds_lfht_destroy(state->channels_ht, NULL);
400 assert(!ret);
401 }
402 if (state->sessions_ht) {
403 ret = cds_lfht_destroy(state->sessions_ht, NULL);
ab0ee2ca
JG
404 assert(!ret);
405 }
1831ae68
FD
406 if (state->trigger_tokens_ht) {
407 ret = cds_lfht_destroy(state->trigger_tokens_ht, NULL);
408 assert(!ret);
409 }
410 if (state->triggers_by_name_ht) {
411 ret = cds_lfht_destroy(state->triggers_by_name_ht, NULL);
412 assert(!ret);
413 }
ea9a44f0
JG
414 /*
415 * Must be destroyed after all channels have been destroyed.
416 * See comment in struct lttng_session_trigger_list.
417 */
418 if (state->session_triggers_ht) {
419 ret = cds_lfht_destroy(state->session_triggers_ht, NULL);
420 assert(!ret);
421 }
ab0ee2ca
JG
422 if (state->notification_channel_socket >= 0) {
423 notification_channel_socket_destroy(
424 state->notification_channel_socket);
425 }
1831ae68
FD
426 if (state->executor) {
427 action_executor_destroy(state->executor);
428 }
ab0ee2ca
JG
429 lttng_poll_clean(&state->events);
430}
431
c8a9de5a
JG
432static
433void mark_thread_as_ready(struct notification_thread_handle *handle)
434{
435 DBG("Marking notification thread as ready");
436 sem_post(&handle->ready);
437}
438
439static
440void wait_until_thread_is_ready(struct notification_thread_handle *handle)
441{
442 DBG("Waiting for notification thread to be ready");
443 sem_wait(&handle->ready);
444 DBG("Notification thread is ready");
445}
446
ab0ee2ca
JG
447static
448int init_thread_state(struct notification_thread_handle *handle,
449 struct notification_thread_state *state)
450{
451 int ret;
452
453 memset(state, 0, sizeof(*state));
454 state->notification_channel_socket = -1;
1831ae68 455 state->trigger_id.token_generator = 1;
ab0ee2ca
JG
456 lttng_poll_init(&state->events);
457
458 ret = notification_channel_socket_create();
459 if (ret < 0) {
460 goto end;
461 }
462 state->notification_channel_socket = ret;
463
464 ret = init_poll_set(&state->events, handle,
465 state->notification_channel_socket);
466 if (ret) {
467 goto end;
468 }
469
470 DBG("[notification-thread] Listening on notification channel socket");
471 ret = lttcomm_listen_unix_sock(state->notification_channel_socket);
472 if (ret < 0) {
473 ERR("[notification-thread] Listen failed on notification channel socket");
474 goto error;
475 }
476
477 state->client_socket_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
478 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
479 if (!state->client_socket_ht) {
480 goto error;
481 }
482
1831ae68
FD
483 state->client_id_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
484 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
485 if (!state->client_id_ht) {
486 goto error;
487 }
488
ab0ee2ca
JG
489 state->channel_triggers_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
490 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
491 if (!state->channel_triggers_ht) {
492 goto error;
493 }
494
ea9a44f0
JG
495 state->session_triggers_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
496 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
497 if (!state->session_triggers_ht) {
498 goto error;
499 }
500
ab0ee2ca
JG
501 state->channel_state_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
502 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
503 if (!state->channel_state_ht) {
504 goto error;
505 }
506
507 state->notification_trigger_clients_ht = cds_lfht_new(DEFAULT_HT_SIZE,
508 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
509 if (!state->notification_trigger_clients_ht) {
510 goto error;
511 }
512
513 state->channels_ht = cds_lfht_new(DEFAULT_HT_SIZE,
514 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
515 if (!state->channels_ht) {
516 goto error;
517 }
8abe313a
JG
518 state->sessions_ht = cds_lfht_new(DEFAULT_HT_SIZE,
519 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
520 if (!state->sessions_ht) {
521 goto error;
522 }
ab0ee2ca
JG
523 state->triggers_ht = cds_lfht_new(DEFAULT_HT_SIZE,
524 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
525 if (!state->triggers_ht) {
526 goto error;
527 }
1831ae68
FD
528 state->trigger_tokens_ht = cds_lfht_new(DEFAULT_HT_SIZE,
529 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
530 if (!state->trigger_tokens_ht) {
531 goto error;
532 }
533 state->triggers_by_name_ht = cds_lfht_new(DEFAULT_HT_SIZE,
534 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
535 if (!state->triggers_by_name_ht) {
536 goto error;
537 }
538 state->executor = action_executor_create(handle);
539 if (!state->executor) {
540 goto error;
541 }
c8a9de5a 542 mark_thread_as_ready(handle);
ab0ee2ca
JG
543end:
544 return 0;
545error:
546 fini_thread_state(state);
547 return -1;
548}
549
550static
551int handle_channel_monitoring_pipe(int fd, uint32_t revents,
552 struct notification_thread_handle *handle,
553 struct notification_thread_state *state)
554{
555 int ret = 0;
556 enum lttng_domain_type domain;
557
558 if (fd == handle->channel_monitoring_pipes.ust32_consumer ||
559 fd == handle->channel_monitoring_pipes.ust64_consumer) {
560 domain = LTTNG_DOMAIN_UST;
561 } else if (fd == handle->channel_monitoring_pipes.kernel_consumer) {
562 domain = LTTNG_DOMAIN_KERNEL;
563 } else {
564 abort();
565 }
566
567 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
568 ret = lttng_poll_del(&state->events, fd);
569 if (ret) {
570 ERR("[notification-thread] Failed to remove consumer monitoring pipe from poll set");
571 }
572 goto end;
573 }
574
575 ret = handle_notification_thread_channel_sample(
576 state, fd, domain);
577 if (ret) {
4149ace8 578 ERR("[notification-thread] Consumer sample handling error occurred");
ab0ee2ca
JG
579 ret = -1;
580 goto end;
581 }
582end:
583 return ret;
584}
585
1831ae68
FD
586static int handle_trigger_event_pipe(int fd,
587 uint32_t revents,
588 struct notification_thread_handle *handle,
589 struct notification_thread_state *state)
590{
591 int ret = 0;
592 enum lttng_domain_type domain;
593
594 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
595 ret = lttng_poll_del(&state->events, fd);
596 if (ret) {
597 ERR("[notification-thread] Failed to remove event monitoring pipe from poll set");
598 }
599 goto end;
600 }
601
602 if (fd == handle->event_trigger_sources.kernel_tracer) {
603 domain = LTTNG_DOMAIN_KERNEL;
604 } else {
605 domain = LTTNG_DOMAIN_UST;
606 }
607
608 ret = handle_notification_thread_event(state, fd, domain);
609 if (ret) {
610 ERR("[notification-thread] Event sample handling error occurred for fd: %d", fd);
611 ret = -1;
612 goto end;
613 }
614end:
615 return ret;
616}
617
618static bool fd_is_event_source(struct notification_thread_handle *handle, int fd)
619{
620 struct notification_event_trigger_source_element *source_element, *tmp;
621 cds_list_for_each_entry_safe(source_element, tmp,
622 &handle->event_trigger_sources.list, node) {
623 if (source_element->fd != fd) {
624 continue;
625 }
626 return true;
627 }
628 if (fd == handle->event_trigger_sources.kernel_tracer) {
629 return true;
630 }
631 return false;
632}
633
ab0ee2ca
JG
634/*
635 * This thread services notification channel clients and commands received
636 * from various lttng-sessiond components over a command queue.
637 */
c8a9de5a 638static
ab0ee2ca
JG
639void *thread_notification(void *data)
640{
641 int ret;
642 struct notification_thread_handle *handle = data;
643 struct notification_thread_state state;
644
645 DBG("[notification-thread] Started notification thread");
646
f620cc28
JG
647 health_register(health_sessiond, HEALTH_SESSIOND_TYPE_NOTIFICATION);
648 rcu_register_thread();
649 rcu_thread_online();
650
ab0ee2ca
JG
651 if (!handle) {
652 ERR("[notification-thread] Invalid thread context provided");
653 goto end;
654 }
655
ab0ee2ca
JG
656 health_code_update();
657
658 ret = init_thread_state(handle, &state);
659 if (ret) {
660 goto end;
661 }
662
ab0ee2ca
JG
663 while (true) {
664 int fd_count, i;
665
666 health_poll_entry();
667 DBG("[notification-thread] Entering poll wait");
668 ret = lttng_poll_wait(&state.events, -1);
669 DBG("[notification-thread] Poll wait returned (%i)", ret);
670 health_poll_exit();
671 if (ret < 0) {
672 /*
673 * Restart interrupted system call.
674 */
675 if (errno == EINTR) {
676 continue;
677 }
678 ERR("[notification-thread] Error encountered during lttng_poll_wait (%i)", ret);
679 goto error;
680 }
681
682 fd_count = ret;
683 for (i = 0; i < fd_count; i++) {
684 int fd = LTTNG_POLL_GETFD(&state.events, i);
685 uint32_t revents = LTTNG_POLL_GETEV(&state.events, i);
686
687 DBG("[notification-thread] Handling fd (%i) activity (%u)", fd, revents);
688
689 if (fd == state.notification_channel_socket) {
690 if (revents & LPOLLIN) {
691 ret = handle_notification_thread_client_connect(
692 &state);
693 if (ret < 0) {
694 goto error;
695 }
696 } else if (revents &
697 (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
698 ERR("[notification-thread] Notification socket poll error");
699 goto error;
700 } else {
701 ERR("[notification-thread] Unexpected poll events %u for notification socket %i", revents, fd);
702 goto error;
703 }
814b4934 704 } else if (fd == lttng_pipe_get_readfd(handle->cmd_queue.event_pipe)) {
ab0ee2ca
JG
705 ret = handle_notification_thread_command(handle,
706 &state);
707 if (ret < 0) {
708 DBG("[notification-thread] Error encountered while servicing command queue");
709 goto error;
710 } else if (ret > 0) {
711 goto exit;
712 }
713 } else if (fd == handle->channel_monitoring_pipes.ust32_consumer ||
714 fd == handle->channel_monitoring_pipes.ust64_consumer ||
715 fd == handle->channel_monitoring_pipes.kernel_consumer) {
716 ret = handle_channel_monitoring_pipe(fd,
717 revents, handle, &state);
718 if (ret) {
719 goto error;
720 }
1831ae68
FD
721 } else if (fd_is_event_source(handle, fd)) {
722 ret = handle_trigger_event_pipe(fd, revents, handle, &state);
723 if (ret) {
724 goto error;
725 }
ab0ee2ca
JG
726 } else {
727 /* Activity on a client's socket. */
728 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
729 /*
730 * It doesn't matter if a command was
731 * pending on the client socket at this
732 * point since it now has no way to
733 * receive the notifications to which
734 * it was subscribing or unsubscribing.
735 */
736 ret = handle_notification_thread_client_disconnect(
737 fd, &state);
738 if (ret) {
739 goto error;
740 }
741 } else {
742 if (revents & LPOLLIN) {
743 ret = handle_notification_thread_client_in(
744 &state, fd);
745 if (ret) {
746 goto error;
747 }
748 }
749
750 if (revents & LPOLLOUT) {
751 ret = handle_notification_thread_client_out(
752 &state, fd);
753 if (ret) {
754 goto error;
755 }
756 }
757 }
758 }
759 }
760 }
761exit:
762error:
763 fini_thread_state(&state);
f620cc28 764end:
ab0ee2ca
JG
765 rcu_thread_offline();
766 rcu_unregister_thread();
f620cc28 767 health_unregister(health_sessiond);
ab0ee2ca
JG
768 return NULL;
769}
c8a9de5a
JG
770
771static
772bool shutdown_notification_thread(void *thread_data)
773{
774 struct notification_thread_handle *handle = thread_data;
775
776 notification_thread_command_quit(handle);
777 return true;
778}
779
4a91420c
JG
780struct lttng_thread *launch_notification_thread(
781 struct notification_thread_handle *handle)
c8a9de5a
JG
782{
783 struct lttng_thread *thread;
784
785 thread = lttng_thread_create("Notification",
786 thread_notification,
787 shutdown_notification_thread,
788 NULL,
789 handle);
790 if (!thread) {
791 goto error;
792 }
793
794 /*
795 * Wait for the thread to be marked as "ready" before returning
796 * as other subsystems depend on the notification subsystem
797 * (e.g. rotation thread).
798 */
799 wait_until_thread_is_ready(handle);
4a91420c 800 return thread;
c8a9de5a 801error:
4a91420c 802 return NULL;
c8a9de5a 803}
This page took 0.075908 seconds and 5 git commands to generate.