Simulate buffer usage in notification thread
[lttng-tools.git] / src / bin / lttng-sessiond / notification-thread.c
CommitLineData
de27ada2
JG
1/*
2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _LGPL_SOURCE
19#include <lttng/trigger/trigger.h>
c254fb11
JG
20#include <lttng/notification/channel-internal.h>
21#include <lttng/notification/notification-internal.h>
22#include <lttng/condition/condition-internal.h>
23#include <lttng/condition/buffer-usage-internal.h>
de27ada2
JG
24#include <common/error.h>
25#include <common/config/session-config.h>
26#include <common/defaults.h>
27#include <common/utils.h>
c254fb11
JG
28#include <common/align.h>
29#include <common/time.h>
de27ada2
JG
30#include <sys/eventfd.h>
31#include <sys/stat.h>
c254fb11
JG
32#include <time.h>
33#include <signal.h>
de27ada2
JG
34
35#include "notification-thread.h"
36#include "lttng-sessiond.h"
37#include "health-sessiond.h"
38
c254fb11
JG
39#include <urcu/list.h>
40
41#define CLIENT_RECEPTION_BUFFER_SIZE (4 * PAGE_SIZE)
42#define SIMULATION_TIMER_INTERVAL_NS 2 * NSEC_PER_SEC
43#define SIMULATION_TIMER_SIGNAL SIGRTMIN + 10
44
45static int simulation_timer_event_fd = -1;
46static timer_t simulation_timer;
47
48struct client {
49 int socket;
50 struct cds_list_head list_node;
51 /*
52 * Conditions to which the client is registered.
53 */
54 struct cds_list_head condition_list;
55};
56
57static struct cds_list_head client_list;
58static struct cds_list_head trigger_list;
59static char *client_reception_buffer;
60
61/*
62 * The simulation timer will alternate between "buffers" between full and
63 * empty values, firing all low/high usage triggers in alternance.
64 */
65static pthread_mutex_t simulation_lock = PTHREAD_MUTEX_INITIALIZER;
66static uint64_t simulation_buffer_use_bytes;
67static double simulation_buffer_use_ratio = 0.0;
68static uint64_t simulation_buffer_capacity = UINT32_MAX;
69
de27ada2
JG
70/*
71 * Destroy the thread data previously created by the init function.
72 */
73void notification_destroy_data(struct notification_thread_data *data)
74{
75 int ret;
76
77 if (!data) {
78 goto end;
79 }
80
81 if (data->cmd_queue.event_fd < 0) {
82 goto end;
83 }
84 ret = close(data->cmd_queue.event_fd);
85 if (ret < 0) {
86 PERROR("close notification command queue event_fd");
87 }
88
c254fb11 89 pthread_mutex_destroy(&data->cmd_queue.lock);
de27ada2
JG
90 /* TODO: purge queue and mark commands as cancelled. */
91end:
92 free(data);
93}
94
95/*
96 * Initialize the thread's data. This MUST be called before the notification
97 * thread is started.
98 */
99struct notification_thread_data *notification_init_data(void)
100{
c254fb11 101 int ret;
de27ada2
JG
102 struct notification_thread_data *data;
103
104 data = zmalloc(sizeof(*data));
105 if (!data) {
106 goto end;
107 }
108
109 data->cmd_queue.event_fd = eventfd(0, EFD_CLOEXEC);
110 if (data->cmd_queue.event_fd < 0) {
111 PERROR("eventfd notification command queue");
112 goto error;
113 }
c254fb11
JG
114 CDS_INIT_LIST_HEAD(&data->cmd_queue.list);
115 ret = pthread_mutex_init(&data->cmd_queue.lock, NULL);
116 if (ret) {
117 goto error;
118 }
de27ada2
JG
119end:
120 return data;
121error:
122 notification_destroy_data(data);
123 return NULL;
124}
125
c254fb11
JG
126static
127void simulation_timer_thread(union sigval val)
128{
129 int ret;
130 uint64_t counter = 1;
131
132 pthread_mutex_lock(&simulation_lock);
133 if (simulation_buffer_use_bytes == 0) {
134 simulation_buffer_use_bytes = UINT32_MAX;
135 simulation_buffer_use_ratio = 1.0;
136 } else {
137 simulation_buffer_use_bytes = 0;
138 simulation_buffer_use_ratio = 0.0;
139 }
140 pthread_mutex_unlock(&simulation_lock);
141 ret = write(simulation_timer_event_fd, &counter, sizeof(counter));
142 if (ret < 0) {
143 PERROR("writer simulation timer event fd");
144 }
145}
146
147static
148int simulation_timer_start(void)
149{
150 int ret;
151 struct sigevent sev;
152 struct itimerspec its;
153
154 ret = eventfd(0, EFD_CLOEXEC);
155 if (ret < 0) {
156 PERROR("eventfd simulation timer event fd");
157 goto error;
158 }
159 simulation_timer_event_fd = ret;
160
161 sev.sigev_notify = SIGEV_THREAD;
162 sev.sigev_value.sival_ptr = NULL;
163 sev.sigev_notify_function = simulation_timer_thread;
164 sev.sigev_notify_attributes = NULL;
165
166 /*
167 * Valgrind indicates a leak when timer_create() is used
168 * in the "SIGEV_THREAD" mode. This bug has been known to upstream glibc
169 * since 2009, but no fix has been implemented so far.
170 */
171 ret = timer_create(CLOCK_MONOTONIC, &sev, &simulation_timer);
172 if (ret < 0) {
173 PERROR("timer_create simulation timer");
174 goto error;
175 }
176
177 its.it_value.tv_sec = SIMULATION_TIMER_INTERVAL_NS / NSEC_PER_SEC;
178 its.it_value.tv_nsec = (SIMULATION_TIMER_INTERVAL_NS % NSEC_PER_SEC);
179 its.it_interval.tv_sec = its.it_value.tv_sec;
180 its.it_interval.tv_nsec = its.it_value.tv_nsec;
181
182 ret = timer_settime(simulation_timer, 0, &its, NULL);
183 if (ret < 0) {
184 PERROR("timer_settime simulation timer");
185 goto error;
186 }
187
188 return 0;
189error:
190 return -1;
191}
192
193static
194void simulation_timer_stop(void)
195{
196 int ret;
197
198 ret = timer_delete(simulation_timer);
199 if (ret == -1) {
200 PERROR("timer_delete simulation timer");
201 }
202}
203
de27ada2
JG
204static
205char *get_notification_channel_sock_path(void)
206{
207 int ret;
208 bool is_root = !getuid();
209 char *sock_path;
210
211 sock_path = zmalloc(LTTNG_PATH_MAX);
212 if (!sock_path) {
213 goto error;
214 }
215
216 if (is_root) {
217 ret = snprintf(sock_path, LTTNG_PATH_MAX,
218 DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK);
219 if (ret < 0) {
220 goto error;
221 }
222 } else {
223 char *home_path = utils_get_home_dir();
224
225 if (!home_path) {
226 ERR("Can't get HOME directory for socket creation");
227 goto error;
228 }
de27ada2
JG
229
230 ret = snprintf(sock_path, LTTNG_PATH_MAX,
231 DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK,
232 home_path);
233 if (ret < 0) {
234 goto error;
235 }
236 }
237
238 return sock_path;
239error:
240 free(sock_path);
241 return NULL;
242}
243
244static
245void notification_channel_socket_destroy(int fd)
246{
247 int ret;
248 char *sock_path = get_notification_channel_sock_path();
249
250 DBG("[notification-thread] Destroying notification channel socket");
251
252 if (sock_path) {
253 ret = unlink(sock_path);
254 free(sock_path);
255 if (ret < 0) {
256 PERROR("unlink notification channel socket");
257 }
258 }
259
260 ret = close(fd);
261 if (ret) {
262 PERROR("close notification channel socket");
263 }
264}
265
266static
267int notification_channel_socket_create(void)
268{
269 int fd = -1, ret;
270 char *sock_path = get_notification_channel_sock_path();
271
272 DBG("[notification-thread] Creating notification channel UNIX socket at %s",
273 sock_path);
274
275 ret = lttcomm_create_unix_sock(sock_path);
276 if (ret < 0) {
277 ERR("[notification-thread] Failed to create notification socket");
278 goto error;
279 }
280 fd = ret;
281
282 ret = chmod(sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
283 if (ret < 0) {
284 ERR("Set file permissions failed: %s", sock_path);
285 PERROR("chmod notification channel socket");
286 goto error;
287 }
288
289 DBG("[notification-thread] Notification channel UNIX socket created (fd = %i)",
290 fd);
291 free(sock_path);
292 return fd;
293error:
294 if (fd >= 0 && close(fd) < 0) {
295 PERROR("close notification channel socket");
296 }
297 free(sock_path);
298 return ret;
299}
300
c254fb11
JG
301static
302int handle_new_connection(int socket)
303{
304 int ret;
305 struct client *client;
306
307 DBG("[notification-thread] Handling new notification channel client connection");
308
309 client = zmalloc(sizeof(*client));
310 if (!client) {
311 goto error;
312 }
313
314 ret = lttcomm_accept_unix_sock(socket);
315 if (ret < 0) {
316 ERR("[notification-thread] Failed to accept new notification channel client connection");
317 goto error;
318 }
319
320 client->socket = ret;
321 CDS_INIT_LIST_HEAD(&client->condition_list);
322
323 /* FIXME handle creds. */
324 ret = lttcomm_setsockopt_creds_unix_sock(socket);
325 if (ret < 0) {
326 ERR("[notification-thread] Failed to set socket options on new notification channel client socket");
327 goto error;
328 }
329
330 cds_list_add(&client->list_node, &client_list);
331 return client->socket;
332error:
333 free(client);
334 return -1;
335}
336
337static
338int send_command_reply(int socket,
339 enum lttng_notification_channel_status status)
340{
341 ssize_t ret;
342 struct lttng_notification_channel_command_reply reply = {
343 .status = (int8_t) status,
344 };
345
346 DBG("[notification-thread] Send command reply (%i)", (int) status);
347
348 ret = lttcomm_send_unix_sock(socket, &reply, sizeof(reply));
349 if (ret < 0) {
350 ERR("[notification-thread] Failed to send command reply");
351 goto error;
352 }
353 return 0;
354error:
355 return -1;
356}
357
358static
359struct client *get_client_from_fd(int fd)
360{
361 struct client *client;
362
363 cds_list_for_each_entry(client, &client_list, list_node) {
364 if (client->socket == fd) {
365 return client;
366 }
367 }
368 return NULL;
369}
370
371static
372int handle_notification_channel_client(int socket)
373{
374 ssize_t ret;
375 size_t received = 0;
376 struct client *client = get_client_from_fd(socket);
377 struct lttng_condition *condition;
378 struct lttng_notification_channel_command command;
379 enum lttng_notification_channel_status status =
380 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
381 struct lttng_trigger *trigger;
382
383 assert(client);
384
385 /* Receive command header. */
386 do
387 {
388 ret = lttcomm_recv_unix_sock(socket, ((char *) &command) + received,
389 sizeof(command) - received);
390 if (ret <= 0) {
391 ERR("[notification-thread] Failed to receive channel command from client (received %zu bytes)", received);
392 goto error_no_reply;
393 }
394 received += ret;
395 } while (received < sizeof(command));
396
397 received = 0;
398 if (command.size >= CLIENT_RECEPTION_BUFFER_SIZE) {
399 ERR("[notification-thread] Notification channel client attempted to send condition larger (%u bytes) than client reception buffer (%u bytes)",
400 command.size,
401 (unsigned int) CLIENT_RECEPTION_BUFFER_SIZE);
402 goto error_no_reply;
403 }
404
405 do
406 {
407 ret = lttcomm_recv_unix_sock(socket,
408 client_reception_buffer + received,
409 command.size - received);
410 if (ret <= 0) {
411 ERR("[notification-thread] Failed to receive condition from client");
412 goto error_no_reply;
413 }
414 received += ret;
415 } while (received < sizeof(command));
416
417 ret = lttng_condition_create_from_buffer(client_reception_buffer,
418 &condition);
419 if (ret < 0 || ret < command.size) {
420 ERR("[notification-thread] Malformed condition received from client");
421 goto error_no_reply;
422 }
423
424 DBG("[notification-thread] Successfully received condition from notification channel client");
425
426 /*
427 * A client may only listen for a condition that is currently associated
428 * with a trigger known to the system.
429 */
430 DBG("[notification-thread] Comparing registered condition to known trigger conditions");
431 cds_list_for_each_entry(trigger, &trigger_list, list_node) {
432 struct lttng_condition *trigger_condition =
433 lttng_trigger_get_condition(trigger);
434
435 if (!trigger_condition) {
436 ERR("[notification-thread] lttng_trigger_get_condition returned NULL");
437 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
438 goto end;
439 }
440
441 if (lttng_condition_is_equal(trigger_condition, condition)) {
442 /* Matching condition found. */
443 DBG("[notification-thread] Found a matching condition, accepting client subscription request");
444 cds_list_add(&condition->list_node,
445 &client->condition_list);
446 goto end;
447 }
448 }
449
450 /* No match found, refuse the subscription. */
451 DBG("[notification-thread] No matching condition found, refusing client subscription request");
452 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN;
453end:
454 if (send_command_reply(socket, status)) {
455 goto error_no_reply;
456 }
457 return 0;
458error_no_reply:
459 return -1;
460}
461
462static
463void client_destroy(struct client *client)
464{
465 struct lttng_condition *condition, *tmp;
466
467 cds_list_for_each_entry_safe(condition, tmp, &client->condition_list,
468 list_node) {
469 cds_list_del(&condition->list_node);
470 lttng_condition_destroy(condition);
471 }
472
473 (void) lttcomm_close_unix_sock(client->socket);
474 free(client);
475}
476
477static
478void clean_up_notification_channel_client(int socket)
479{
480 struct client *client;
481
482 DBG("[notification-thread] Searching for client data for clean-up");
483 cds_list_for_each_entry(client, &client_list, list_node) {
484 if (client->socket == socket) {
485 DBG("[notification-thread] Client data found for clean-up");
486 cds_list_del(&client->list_node);
487 client_destroy(client);
488 return;
489 }
490 }
491 ERR("[notification-thread] Failed to clean-up client data");
492}
493
494static
495void activate_triggers(struct cds_list_head *new_triggers_list)
496{
497 struct lttng_trigger *trigger, *tmp;
498
499 DBG("[notification-thread] Moving triggers from new list to activated trigger set");
500 cds_list_for_each_entry_safe(trigger, tmp, new_triggers_list, list_node) {
501 cds_list_del(&trigger->list_node);
502 cds_list_add(&trigger->list_node, &trigger_list);
503 }
504}
505
506static
507void clean_up_triggers(void)
508{
509 struct lttng_trigger *trigger, *tmp;
510
511 DBG("[notification-thread] Cleaning up triggers");
512 cds_list_for_each_entry_safe(trigger, tmp, &trigger_list, list_node) {
513 DBG("[notification-thread] Destroying trigger");
514 cds_list_del(&trigger->list_node);
515 lttng_trigger_destroy(trigger);
516 }
517}
518
519static
520struct lttng_evaluation *evaluate_buffer_usage_condition(
521 struct lttng_condition *_condition)
522{
523 uint64_t threshold;
524 struct lttng_evaluation *evaluation = NULL;
525 struct lttng_condition_buffer_usage *condition = container_of(
526 _condition, struct lttng_condition_buffer_usage,
527 parent);
528
529 if (condition->threshold_bytes.set) {
530 threshold = condition->threshold_bytes.value;
531 } else {
532 /* Threshold was expressed as a ratio. */
533 threshold = (uint64_t) (condition->threshold_ratio.value *
534 (double) simulation_buffer_capacity);
535 }
536
537 if (condition->parent.type ==
538 LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW) {
539 if (simulation_buffer_use_bytes <= threshold) {
540 evaluation = lttng_evaluation_buffer_usage_create(
541 condition->parent.type,
542 simulation_buffer_use_bytes,
543 simulation_buffer_capacity);
544 }
545 } else {
546 if (simulation_buffer_use_bytes >= threshold) {
547 evaluation = lttng_evaluation_buffer_usage_create(
548 condition->parent.type,
549 simulation_buffer_use_bytes,
550 simulation_buffer_capacity);
551 }
552 }
553 return evaluation;
554}
555
556static
557void notify_client(struct client *client, struct lttng_condition *condition,
558 struct lttng_evaluation *evaluation)
559{
560 ssize_t notification_size, ret;
561 char *notification_buffer;
562 struct lttng_notification *notification;
563
564 notification = lttng_notification_create(condition, evaluation);
565 if (!notification) {
566 ERR("[notification-thread] Failed to create client notification");
567 return;
568 }
569
570 notification_size = lttng_notification_serialize(notification, NULL);
571 if (notification_size < 0) {
572 ERR("[notification-thread] Failed to get size of serialized notification");
573 return;
574 }
575
576 notification_buffer = zmalloc(notification_size);
577 if (!notification_buffer) {
578 ERR("[notification-thread] Failed to allocate notification serialization buffer");
579 }
580
581 ret = lttng_notification_serialize(notification, notification_buffer);
582 if (ret != notification_size) {
583 ERR("[notification-thread] Failed to serialize notification");
584 return;
585 }
586
587 ret = lttcomm_send_unix_sock(client->socket, notification_buffer,
588 notification_size);
589 if (ret < 0) {
590 ERR("[notification-thread] Failed to send notification to client");
591 return;
592 }
593}
594
595static
596void evaluate_client_conditions(void)
597{
598 struct client *client;
599
600 DBG("[notification-thread] Evaluating client conditions");
601 cds_list_for_each_entry(client, &client_list, list_node) {
602 struct lttng_condition *condition;
603 cds_list_for_each_entry(condition, &client->condition_list,
604 list_node) {
605 struct lttng_evaluation *evaluation = NULL;
606 switch (lttng_condition_get_type(condition)) {
607 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
608 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
609 evaluation = evaluate_buffer_usage_condition(
610 condition);
611 break;
612 default:
613 ERR("[notification-thread] Unknown condition type encountered in evaluation");
614 abort();
615 }
616
617 if (evaluation) {
618 DBG("[notification-thread] Condition evaluated to true");
619 notify_client(client, condition, evaluation);
620 lttng_evaluation_destroy(evaluation);
621 }
622 }
623 }
624 DBG("[notification-thread] Client conditions evaluated");
625}
626
de27ada2
JG
627/*
628 * This thread services notification channel clients and received notifications
629 * from various lttng-sessiond components over a command queue.
630 */
631void *thread_notification(void *data)
632{
633 int ret;
634 struct lttng_poll_event events;
635 int notification_channel_socket;
636 struct notification_thread_data *ctx = data;
637
638 DBG("[notification-thread] Started notification thread");
639
c254fb11
JG
640 CDS_INIT_LIST_HEAD(&client_list);
641 CDS_INIT_LIST_HEAD(&trigger_list);
642
643 simulation_timer_start();
644
de27ada2
JG
645 if (!ctx) {
646 ERR("[notification-thread] Invalid thread context provided");
647 goto end;
648 }
649
650 rcu_register_thread();
651 rcu_thread_online();
652
653 health_register(health_sessiond, HEALTH_SESSIOND_TYPE_NOTIFICATION);
654 health_code_update();
655
c254fb11
JG
656 client_reception_buffer = zmalloc(CLIENT_RECEPTION_BUFFER_SIZE);
657 if (!client_reception_buffer) {
658 ERR("[notification-thread] Failed to allocate client reception buffer");
659 goto end;
660 }
661
662 ret = notification_channel_socket_create();
663 if (ret < 0) {
664 goto end;
665 }
666 notification_channel_socket = ret;
de27ada2
JG
667
668 /*
669 * Create pollset with size 2, quit pipe and notification channel
670 * socket, and the command queue event fd.
671 */
672 ret = sessiond_set_thread_pollset(&events, 3);
673 if (ret < 0) {
674 goto error_poll_create;
675 }
676
677 /* Add notification channel socket to poll set. */
678 ret = lttng_poll_add(&events, notification_channel_socket,
679 LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP);
680 if (ret < 0) {
681 ERR("[notification-thread] Failed to add notification channel socket to pollset");
682 goto error;
683 }
684
685 ret = lttng_poll_add(&events, ctx->cmd_queue.event_fd,
686 LPOLLIN | LPOLLERR);
687 if (ret < 0) {
688 ERR("[notification-thread] Failed to add notification command queue event fd to pollset");
689 goto error;
690 }
691
c254fb11
JG
692 ret = lttng_poll_add(&events, simulation_timer_event_fd,
693 LPOLLIN | LPOLLERR);
694 if (ret < 0) {
695 ERR("[notification-thread] Failed to add timer event fd to pollset");
696 goto error;
697 }
698
de27ada2
JG
699 DBG("[notification-thread] Listening on notification channel socket");
700 ret = lttcomm_listen_unix_sock(notification_channel_socket);
701 if (ret < 0) {
702 ERR("[notification-thread] Listen failed on notification channel socket");
703 goto error;
704 }
705
706 while (true) {
707 int fd_count, i;
708
709 health_poll_entry();
710 DBG("[notification-thread] Entering poll wait");
711 ret = lttng_poll_wait(&events, -1);
712 DBG("[notification-thread] Poll wait returned (%i)", ret);
713 health_poll_exit();
714 if (ret < 0) {
715 /*
716 * Restart interrupted system call.
717 */
718 if (errno == EINTR) {
719 continue;
720 }
721 ERR("[notification-thread] Error encountered during lttng_poll_wait (%i)", ret);
722 goto error;
723 }
724
725 fd_count = ret;
726 for (i = 0; i < fd_count; i++) {
727 int fd = LTTNG_POLL_GETFD(&events, i);
728 uint32_t revents = LTTNG_POLL_GETEV(&events, i);
729
c254fb11
JG
730 DBG("[notification-thread] Handling fd (%i) activity (%u)", fd, revents);
731
de27ada2
JG
732 /* Thread quit pipe has been closed. Killing thread. */
733 if (sessiond_check_thread_quit_pipe(fd, revents)) {
734 DBG("[notification-thread] Quit pipe signaled, exiting.");
735 goto exit;
736 }
c254fb11
JG
737
738 if (fd == notification_channel_socket) {
739 if (revents & LPOLLIN) {
740 int new_socket;
741
742 ret = handle_new_connection(
743 notification_channel_socket);
744 if (ret < 0) {
745 continue;
746 }
747 new_socket = ret;
748
749 ret = lttng_poll_add(&events, new_socket,
750 LPOLLIN | LPOLLERR |
751 LPOLLHUP | LPOLLRDHUP);
752 if (ret < 0) {
753 ERR("[notification-thread] Failed to add notification channel client socket to pollset");
754 goto error;
755 }
756 DBG("[notification-thread] Added new notification channel client socket to poll set");
757 } else if (revents &
758 (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
759 ERR("[notification-thread] Notification socket poll error");
760 goto error;
761 } else {
762 ERR("[notification-thread] Unexpected poll events %u for notification socket %i", revents, fd);
763 goto error;
764 }
765 } else if (fd == ctx->cmd_queue.event_fd) {
766 /*
767 * Handling of internaly-generated events to
768 * evaluate against the set of active
769 * conditions.
770 */
771 uint64_t counter;
772
773 DBG("[notification-thread] Event received on command queue event fd");
774 ret = read(fd, &counter, sizeof(counter));
775 if (ret < 0) {
776 ERR("read on command queue event fd");
777 }
778
779 pthread_mutex_lock(&ctx->cmd_queue.lock);
780 activate_triggers(&ctx->cmd_queue.list);
781 pthread_mutex_unlock(&ctx->cmd_queue.lock);
782 } else if (fd == simulation_timer_event_fd) {
783 /*
784 * Place-holder timer to simulate activity in
785 * the system.
786 */
787 uint64_t counter;
788
789 DBG("[notification-thread] Simulation timer fired");
790 ret = read(fd, &counter, sizeof(counter));
791 if (ret < 0) {
792 ERR("read on simulation timer event fd");
793 }
794
795 pthread_mutex_lock(&simulation_lock);
796 evaluate_client_conditions();
797 pthread_mutex_unlock(&simulation_lock);
798 } else {
799 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
800 /*
801 * It doesn't matter if a command was
802 * pending on the client socket at this
803 * point since it now has now way to
804 * receive the notifications to which
805 * it was subscribing or unsubscribing.
806 */
807 DBG("[notification-thread] Closing client connection (fd = %i)", fd);
808 clean_up_notification_channel_client(fd);
809 } else if (revents & LPOLLIN) {
810 ret = handle_notification_channel_client(fd);
811 if (ret) {
812 DBG("[notification-thread] Closing client connection following error");
813 clean_up_notification_channel_client(fd);
814 }
815 } else {
816 DBG("[notification-thread] Unexpected poll events %u for notification socket %i", revents, fd);
817 }
818 }
de27ada2
JG
819 }
820 }
821exit:
822
823error:
824 lttng_poll_clean(&events);
825error_poll_create:
826 notification_channel_socket_destroy(notification_channel_socket);
827 health_unregister(health_sessiond);
828 rcu_thread_offline();
829 rcu_unregister_thread();
c254fb11
JG
830 free(client_reception_buffer);
831 clean_up_triggers();
de27ada2 832end:
c254fb11 833 simulation_timer_stop();
de27ada2
JG
834 return NULL;
835}
This page took 0.056991 seconds and 5 git commands to generate.