Build a list of triggers applying to a given session on creation
[lttng-tools.git] / src / bin / lttng-sessiond / rotation-thread.c
1 /*
2 * Copyright (C) 2017 - Julien Desfossez <jdesfossez@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>
20 #include <common/error.h>
21 #include <common/config/session-config.h>
22 #include <common/defaults.h>
23 #include <common/utils.h>
24 #include <common/futex.h>
25 #include <common/align.h>
26 #include <common/time.h>
27 #include <common/hashtable/utils.h>
28 #include <sys/eventfd.h>
29 #include <sys/stat.h>
30 #include <time.h>
31 #include <signal.h>
32 #include <inttypes.h>
33
34 #include <common/kernel-ctl/kernel-ctl.h>
35 #include <lttng/notification/channel-internal.h>
36 #include <lttng/rotate-internal.h>
37
38 #include "rotation-thread.h"
39 #include "lttng-sessiond.h"
40 #include "health-sessiond.h"
41 #include "rotate.h"
42 #include "cmd.h"
43 #include "session.h"
44 #include "sessiond-timer.h"
45
46 #include <urcu.h>
47 #include <urcu/list.h>
48 #include <urcu/rculfhash.h>
49
50 /*
51 * Store a struct rotation_channel_info for each channel that is currently
52 * being rotated by the consumer.
53 */
54 struct cds_lfht *channel_pending_rotate_ht;
55
56 struct lttng_notification_channel *rotate_notification_channel = NULL;
57
58 struct rotation_thread_state {
59 struct lttng_poll_event events;
60 };
61
62 static
63 void channel_rotation_info_destroy(struct rotation_channel_info *channel_info)
64 {
65 assert(channel_info);
66 free(channel_info);
67 }
68
69 static
70 int match_channel_info(struct cds_lfht_node *node, const void *key)
71 {
72 struct rotation_channel_key *channel_key = (struct rotation_channel_key *) key;
73 struct rotation_channel_info *channel_info;
74
75 channel_info = caa_container_of(node, struct rotation_channel_info,
76 rotate_channels_ht_node);
77
78 return !!((channel_key->key == channel_info->channel_key.key) &&
79 (channel_key->domain == channel_info->channel_key.domain));
80 }
81
82 static
83 struct rotation_channel_info *lookup_channel_pending(uint64_t key,
84 enum lttng_domain_type domain)
85 {
86 struct cds_lfht_iter iter;
87 struct cds_lfht_node *node;
88 struct rotation_channel_info *channel_info = NULL;
89 struct rotation_channel_key channel_key = { .key = key,
90 .domain = domain };
91
92 cds_lfht_lookup(channel_pending_rotate_ht,
93 hash_channel_key(&channel_key),
94 match_channel_info,
95 &channel_key, &iter);
96 node = cds_lfht_iter_get_node(&iter);
97 if (!node) {
98 goto end;
99 }
100
101 channel_info = caa_container_of(node, struct rotation_channel_info,
102 rotate_channels_ht_node);
103 cds_lfht_del(channel_pending_rotate_ht, node);
104 end:
105 return channel_info;
106 }
107
108 /*
109 * Destroy the thread data previously created by the init function.
110 */
111 void rotation_thread_handle_destroy(
112 struct rotation_thread_handle *handle)
113 {
114 int ret;
115
116 if (!handle) {
117 goto end;
118 }
119
120 if (handle->ust32_consumer >= 0) {
121 ret = close(handle->ust32_consumer);
122 if (ret) {
123 PERROR("close 32-bit consumer channel rotation pipe");
124 }
125 }
126 if (handle->ust64_consumer >= 0) {
127 ret = close(handle->ust64_consumer);
128 if (ret) {
129 PERROR("close 64-bit consumer channel rotation pipe");
130 }
131 }
132 if (handle->kernel_consumer >= 0) {
133 ret = close(handle->kernel_consumer);
134 if (ret) {
135 PERROR("close kernel consumer channel rotation pipe");
136 }
137 }
138
139 end:
140 free(handle);
141 }
142
143 struct rotation_thread_handle *rotation_thread_handle_create(
144 struct lttng_pipe *ust32_channel_rotate_pipe,
145 struct lttng_pipe *ust64_channel_rotate_pipe,
146 struct lttng_pipe *kernel_channel_rotate_pipe,
147 int thread_quit_pipe,
148 struct rotation_thread_timer_queue *rotation_timer_queue,
149 struct notification_thread_handle *notification_thread_handle,
150 sem_t *notification_thread_ready)
151 {
152 struct rotation_thread_handle *handle;
153
154 handle = zmalloc(sizeof(*handle));
155 if (!handle) {
156 goto end;
157 }
158
159 if (ust32_channel_rotate_pipe) {
160 handle->ust32_consumer =
161 lttng_pipe_release_readfd(
162 ust32_channel_rotate_pipe);
163 if (handle->ust32_consumer < 0) {
164 goto error;
165 }
166 } else {
167 handle->ust32_consumer = -1;
168 }
169 if (ust64_channel_rotate_pipe) {
170 handle->ust64_consumer =
171 lttng_pipe_release_readfd(
172 ust64_channel_rotate_pipe);
173 if (handle->ust64_consumer < 0) {
174 goto error;
175 }
176 } else {
177 handle->ust64_consumer = -1;
178 }
179 if (kernel_channel_rotate_pipe) {
180 handle->kernel_consumer =
181 lttng_pipe_release_readfd(
182 kernel_channel_rotate_pipe);
183 if (handle->kernel_consumer < 0) {
184 goto error;
185 }
186 } else {
187 handle->kernel_consumer = -1;
188 }
189 handle->thread_quit_pipe = thread_quit_pipe;
190 handle->rotation_timer_queue = rotation_timer_queue;
191 handle->notification_thread_handle = notification_thread_handle;
192 handle->notification_thread_ready = notification_thread_ready;
193
194 end:
195 return handle;
196 error:
197 rotation_thread_handle_destroy(handle);
198 return NULL;
199 }
200
201 static
202 int init_poll_set(struct lttng_poll_event *poll_set,
203 struct rotation_thread_handle *handle)
204 {
205 int ret;
206
207 /*
208 * Create pollset with size 5:
209 * - sessiond quit pipe
210 * - sessiond timer pipe,
211 * - consumerd (32-bit user space) channel rotate pipe,
212 * - consumerd (64-bit user space) channel rotate pipe,
213 * - consumerd (kernel) channel rotate pipe,
214 */
215 ret = lttng_poll_create(poll_set, 5, LTTNG_CLOEXEC);
216 if (ret < 0) {
217 goto end;
218 }
219
220 ret = lttng_poll_add(poll_set, handle->thread_quit_pipe,
221 LPOLLIN | LPOLLERR);
222 if (ret < 0) {
223 ERR("[rotation-thread] Failed to add thread_quit_pipe fd to pollset");
224 goto error;
225 }
226 ret = lttng_poll_add(poll_set,
227 lttng_pipe_get_readfd(handle->rotation_timer_queue->event_pipe),
228 LPOLLIN | LPOLLERR);
229 if (ret < 0) {
230 ERR("[rotation-thread] Failed to add rotate_pending fd to pollset");
231 goto error;
232 }
233 ret = lttng_poll_add(poll_set, handle->ust32_consumer,
234 LPOLLIN | LPOLLERR);
235 if (ret < 0) {
236 ERR("[rotation-thread] Failed to add ust-32 channel rotation pipe fd to pollset");
237 goto error;
238 }
239 ret = lttng_poll_add(poll_set, handle->ust64_consumer,
240 LPOLLIN | LPOLLERR);
241 if (ret < 0) {
242 ERR("[rotation-thread] Failed to add ust-64 channel rotation pipe fd to pollset");
243 goto error;
244 }
245 if (handle->kernel_consumer >= 0) {
246 ret = lttng_poll_add(poll_set, handle->kernel_consumer,
247 LPOLLIN | LPOLLERR);
248 if (ret < 0) {
249 ERR("[rotation-thread] Failed to add kernel channel rotation pipe fd to pollset");
250 goto error;
251 }
252 }
253
254 end:
255 return ret;
256 error:
257 lttng_poll_clean(poll_set);
258 return ret;
259 }
260
261 static
262 void fini_thread_state(struct rotation_thread_state *state)
263 {
264 int ret;
265
266 lttng_poll_clean(&state->events);
267 ret = cds_lfht_destroy(channel_pending_rotate_ht, NULL);
268 assert(!ret);
269 if (rotate_notification_channel) {
270 lttng_notification_channel_destroy(rotate_notification_channel);
271 }
272 }
273
274 static
275 int init_thread_state(struct rotation_thread_handle *handle,
276 struct rotation_thread_state *state)
277 {
278 int ret;
279
280 memset(state, 0, sizeof(*state));
281 lttng_poll_init(&state->events);
282
283 ret = init_poll_set(&state->events, handle);
284 if (ret) {
285 ERR("[rotation-thread] Failed to initialize rotation thread poll set");
286 goto end;
287 }
288
289 channel_pending_rotate_ht = cds_lfht_new(DEFAULT_HT_SIZE,
290 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
291 if (!channel_pending_rotate_ht) {
292 ERR("[rotation-thread] Failed to create channel pending rotation hash table");
293 ret = -1;
294 goto end;
295 }
296
297 /*
298 * We wait until the notification thread is ready to create the
299 * notification channel and add it to the poll_set.
300 */
301 sem_wait(handle->notification_thread_ready);
302 rotate_notification_channel = lttng_notification_channel_create(
303 lttng_session_daemon_notification_endpoint);
304 if (!rotate_notification_channel) {
305 ERR("[rotation-thread] Could not create notification channel");
306 ret = -1;
307 goto end;
308 }
309 ret = lttng_poll_add(&state->events, rotate_notification_channel->socket,
310 LPOLLIN | LPOLLERR);
311 if (ret < 0) {
312 ERR("[rotation-thread] Failed to add notification fd to pollset");
313 goto end;
314 }
315
316 end:
317 return ret;
318 }
319
320 static
321 int handle_channel_rotation_pipe(int fd, uint32_t revents,
322 struct rotation_thread_handle *handle,
323 struct rotation_thread_state *state)
324 {
325 int ret = 0;
326 enum lttng_domain_type domain;
327 struct rotation_channel_info *channel_info;
328 struct ltt_session *session = NULL;
329 uint64_t key;
330
331 if (fd == handle->ust32_consumer ||
332 fd == handle->ust64_consumer) {
333 domain = LTTNG_DOMAIN_UST;
334 } else if (fd == handle->kernel_consumer) {
335 domain = LTTNG_DOMAIN_KERNEL;
336 } else {
337 ERR("[rotation-thread] Unknown channel rotation pipe fd %d",
338 fd);
339 abort();
340 }
341
342 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
343 ret = lttng_poll_del(&state->events, fd);
344 if (ret) {
345 ERR("[rotation-thread] Failed to remove consumer "
346 "rotation pipe from poll set");
347 }
348 goto end;
349 }
350
351 do {
352 ret = read(fd, &key, sizeof(key));
353 } while (ret == -1 && errno == EINTR);
354 if (ret != sizeof(key)) {
355 ERR("[rotation-thread] Failed to read from pipe (fd = %i)",
356 fd);
357 ret = -1;
358 goto end;
359 }
360
361 DBG("[rotation-thread] Received notification for chan %" PRIu64
362 ", domain %d", key, domain);
363
364 channel_info = lookup_channel_pending(key, domain);
365 if (!channel_info) {
366 ERR("[rotation-thread] Failed to find channel_info (key = %"
367 PRIu64 ")", key);
368 ret = -1;
369 goto end;
370 }
371 rcu_read_lock();
372 session_lock_list();
373 session = session_find_by_id(channel_info->session_id);
374 if (!session) {
375 /*
376 * The session may have been destroyed before we had a chance to
377 * perform this action, return gracefully.
378 */
379 DBG("[rotation-thread] Session %" PRIu64 " not found",
380 channel_info->session_id);
381 ret = 0;
382 goto end_unlock_session_list;
383 }
384
385 session_lock(session);
386 if (--session->nr_chan_rotate_pending == 0) {
387 time_t now = time(NULL);
388
389 if (now == (time_t) -1) {
390 session->rotation_state = LTTNG_ROTATION_STATE_ERROR;
391 ret = LTTNG_ERR_UNK;
392 goto end_unlock_session;
393 }
394
395 ret = rename_complete_chunk(session, now);
396 if (ret < 0) {
397 ERR("Failed to rename completed rotation chunk");
398 goto end_unlock_session;
399 }
400 session->rotate_pending = false;
401 session->last_chunk_start_ts = session->current_chunk_start_ts;
402 if (session->rotate_pending_relay) {
403 ret = sessiond_timer_rotate_pending_start(
404 session,
405 DEFAULT_ROTATE_PENDING_RELAY_TIMER);
406 if (ret) {
407 ERR("Failed to enable rotate pending timer");
408 ret = -1;
409 goto end_unlock_session;
410 }
411 } else {
412 session->rotation_state = LTTNG_ROTATION_STATE_COMPLETED;
413 }
414 DBG("Rotation completed for session %s", session->name);
415 }
416
417 ret = 0;
418
419 end_unlock_session:
420 channel_rotation_info_destroy(channel_info);
421 session_unlock(session);
422 end_unlock_session_list:
423 session_unlock_list();
424 rcu_read_unlock();
425 end:
426 return ret;
427 }
428
429 /*
430 * Process the rotate_pending check, called with session lock held.
431 */
432 static
433 int rotate_pending_relay_timer(struct ltt_session *session)
434 {
435 int ret;
436
437 DBG("[rotation-thread] Check rotate pending on session %" PRIu64,
438 session->id);
439 ret = relay_rotate_pending(session, session->current_archive_id - 1);
440 if (ret < 0) {
441 ERR("[rotation-thread] Check relay rotate pending");
442 goto end;
443 }
444 if (ret == 0) {
445 DBG("[rotation-thread] Rotation completed on the relay for "
446 "session %" PRIu64, session->id);
447 /*
448 * Now we can clear the pending flag in the session. New
449 * rotations can start now.
450 */
451 session->rotate_pending_relay = false;
452 session->rotation_state = LTTNG_ROTATION_STATE_COMPLETED;
453 } else if (ret == 1) {
454 DBG("[rotation-thread] Rotation still pending on the relay for "
455 "session %" PRIu64, session->id);
456 ret = sessiond_timer_rotate_pending_start(session,
457 DEFAULT_ROTATE_PENDING_RELAY_TIMER);
458 if (ret) {
459 ERR("Re-enabling rotate pending timer");
460 ret = -1;
461 goto end;
462 }
463 }
464
465 ret = 0;
466
467 end:
468 return ret;
469 }
470
471 /*
472 * Process the rotate_timer, called with session lock held.
473 */
474 static
475 int rotate_timer(struct ltt_session *session)
476 {
477 int ret;
478
479 /*
480 * Complete _at most_ one scheduled rotation on a stopped session.
481 */
482 if (!session->active && session->rotate_timer_enabled &&
483 session->rotated_after_last_stop) {
484 ret = 0;
485 goto end;
486 }
487
488 /* Ignore this timer if a rotation is already in progress. */
489 if (session->rotate_pending || session->rotate_pending_relay) {
490 ret = 0;
491 goto end;
492 }
493
494 DBG("[rotation-thread] Rotate timer on session %s", session->name);
495
496 ret = cmd_rotate_session(session, NULL);
497 if (ret == -LTTNG_ERR_ROTATION_PENDING) {
498 DBG("Scheduled rotation aborted since a rotation is already in progress");
499 ret = 0;
500 goto end;
501 } else if (ret != LTTNG_OK) {
502 ERR("[rotation-thread] Automatic time-triggered rotation failed with error code %i", ret);
503 ret = -1;
504 goto end;
505 }
506
507 ret = 0;
508
509 end:
510 return ret;
511 }
512
513 static
514 int handle_rotate_timer_pipe(uint32_t revents,
515 struct rotation_thread_handle *handle,
516 struct rotation_thread_state *state,
517 struct rotation_thread_timer_queue *queue)
518 {
519 int ret = 0;
520 int fd = lttng_pipe_get_readfd(queue->event_pipe);
521 struct ltt_session *session;
522 char buf[1];
523
524 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
525 ret = lttng_poll_del(&state->events, fd);
526 if (ret) {
527 ERR("[rotation-thread] Failed to remove consumer "
528 "rotate pending pipe from poll set");
529 }
530 goto end;
531 }
532
533 ret = lttng_read(fd, buf, 1);
534 if (ret != 1) {
535 ERR("[rotation-thread] Failed to read from wakeup pipe (fd = %i)", fd);
536 ret = -1;
537 goto end;
538 }
539
540 for (;;) {
541 struct sessiond_rotation_timer *timer_data;
542
543 /*
544 * Take the queue lock only to pop elements from the list.
545 */
546 pthread_mutex_lock(&queue->lock);
547 if (cds_list_empty(&queue->list)) {
548 pthread_mutex_unlock(&queue->lock);
549 break;
550 }
551 timer_data = cds_list_first_entry(&queue->list,
552 struct sessiond_rotation_timer, head);
553 cds_list_del(&timer_data->head);
554 pthread_mutex_unlock(&queue->lock);
555
556 /*
557 * session lock to lookup the session ID.
558 */
559 session_lock_list();
560 session = session_find_by_id(timer_data->session_id);
561 if (!session) {
562 DBG("[rotation-thread] Session %" PRIu64 " not found",
563 timer_data->session_id);
564 /*
565 * This is a non-fatal error, and we cannot report it to the
566 * user (timer), so just print the error and continue the
567 * processing.
568 */
569 session_unlock_list();
570 free(timer_data);
571 continue;
572 }
573
574 /*
575 * Take the session lock and release the session_list lock.
576 */
577 session_lock(session);
578 session_unlock_list();
579
580 if (timer_data->signal == LTTNG_SESSIOND_SIG_ROTATE_PENDING) {
581 ret = rotate_pending_relay_timer(session);
582 } else if (timer_data->signal == LTTNG_SESSIOND_SIG_ROTATE_TIMER) {
583 ret = rotate_timer(session);
584 } else {
585 ERR("Unknown signal in rotate timer %d", timer_data->signal);
586 ret = -1;
587 }
588 session_unlock(session);
589 free(timer_data);
590 if (ret) {
591 ERR("Error processing timer");
592 goto end;
593 }
594 }
595
596 ret = 0;
597
598 end:
599 return ret;
600 }
601
602 int handle_condition(
603 const struct lttng_condition *condition,
604 const struct lttng_evaluation *evaluation,
605 struct notification_thread_handle *notification_thread_handle)
606 {
607 int ret = 0;
608 const char *condition_session_name = NULL;
609 enum lttng_condition_type condition_type;
610 enum lttng_condition_status condition_status;
611 enum lttng_evaluation_status evaluation_status;
612 uint64_t consumed;
613 struct ltt_session *session;
614
615 condition_type = lttng_condition_get_type(condition);
616
617 if (condition_type != LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE) {
618 ret = -1;
619 ERR("[rotation-thread] Condition type and session usage type are not the same");
620 goto end;
621 }
622
623 /* Fetch info to test */
624 condition_status = lttng_condition_session_consumed_size_get_session_name(
625 condition, &condition_session_name);
626 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
627 ERR("[rotation-thread] Session name could not be fetched");
628 ret = -1;
629 goto end;
630 }
631 evaluation_status = lttng_evaluation_session_consumed_size_get_consumed_size(evaluation,
632 &consumed);
633 if (evaluation_status != LTTNG_EVALUATION_STATUS_OK) {
634 ERR("[rotation-thread] Failed to get evaluation");
635 ret = -1;
636 goto end;
637 }
638
639 session_lock_list();
640 session = session_find_by_name(condition_session_name);
641 if (!session) {
642 ret = -1;
643 session_unlock_list();
644 ERR("[rotation-thread] Session \"%s\" not found",
645 condition_session_name);
646 goto end;
647 }
648 session_lock(session);
649 session_unlock_list();
650
651 ret = unsubscribe_session_consumed_size_rotation(session,
652 notification_thread_handle);
653 if (ret) {
654 goto end;
655 }
656
657 ret = cmd_rotate_session(session, NULL);
658 if (ret == -LTTNG_ERR_ROTATION_PENDING) {
659 DBG("Rotate already pending, subscribe to the next threshold value");
660 ret = 0;
661 } else if (ret != LTTNG_OK) {
662 ERR("[rotation-thread] Failed to rotate on size notification with error: %s",
663 lttng_strerror(ret));
664 ret = -1;
665 goto end_unlock;
666 }
667 ret = subscribe_session_consumed_size_rotation(session,
668 consumed + session->rotate_size,
669 notification_thread_handle);
670 if (ret) {
671 ERR("[rotation-thread] Failed to subscribe to session consumed size condition");
672 goto end_unlock;
673 }
674 ret = 0;
675
676 end_unlock:
677 session_unlock(session);
678 end:
679 return ret;
680 }
681
682 static
683 int handle_notification_channel(int fd, uint32_t revents,
684 struct rotation_thread_handle *handle,
685 struct rotation_thread_state *state)
686 {
687 int ret;
688 bool notification_pending;
689 struct lttng_notification *notification = NULL;
690 enum lttng_notification_channel_status status;
691 const struct lttng_evaluation *notification_evaluation;
692 const struct lttng_condition *notification_condition;
693
694 status = lttng_notification_channel_has_pending_notification(
695 rotate_notification_channel, &notification_pending);
696 if (status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
697 ERR("[rotation-thread ]Error occured while checking for pending notification");
698 ret = -1;
699 goto end;
700 }
701
702 if (!notification_pending) {
703 ret = 0;
704 goto end;
705 }
706
707 /* Receive the next notification. */
708 status = lttng_notification_channel_get_next_notification(
709 rotate_notification_channel,
710 &notification);
711
712 switch (status) {
713 case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
714 break;
715 case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
716 /* Not an error, we will wait for the next one */
717 ret = 0;
718 goto end;;
719 case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
720 ERR("Notification channel was closed");
721 ret = -1;
722 goto end;
723 default:
724 /* Unhandled conditions / errors. */
725 ERR("Unknown notification channel status");
726 ret = -1;
727 goto end;
728 }
729
730 notification_condition = lttng_notification_get_condition(notification);
731 notification_evaluation = lttng_notification_get_evaluation(notification);
732
733 ret = handle_condition(notification_condition, notification_evaluation,
734 handle->notification_thread_handle);
735
736 end:
737 lttng_notification_destroy(notification);
738 return ret;
739 }
740
741 void *thread_rotation(void *data)
742 {
743 int ret;
744 struct rotation_thread_handle *handle = data;
745 struct rotation_thread_state state;
746
747 DBG("[rotation-thread] Started rotation thread");
748
749 if (!handle) {
750 ERR("[rotation-thread] Invalid thread context provided");
751 goto end;
752 }
753
754 rcu_register_thread();
755 rcu_thread_online();
756
757 health_register(health_sessiond, HEALTH_SESSIOND_TYPE_ROTATION);
758 health_code_update();
759
760 ret = init_thread_state(handle, &state);
761 if (ret) {
762 goto end;
763 }
764
765 /* Ready to handle client connections. */
766 sessiond_notify_ready();
767
768 while (true) {
769 int fd_count, i;
770
771 health_poll_entry();
772 DBG("[rotation-thread] Entering poll wait");
773 ret = lttng_poll_wait(&state.events, -1);
774 DBG("[rotation-thread] Poll wait returned (%i)", ret);
775 health_poll_exit();
776 if (ret < 0) {
777 /*
778 * Restart interrupted system call.
779 */
780 if (errno == EINTR) {
781 continue;
782 }
783 ERR("[rotation-thread] Error encountered during lttng_poll_wait (%i)", ret);
784 goto error;
785 }
786
787 fd_count = ret;
788 for (i = 0; i < fd_count; i++) {
789 int fd = LTTNG_POLL_GETFD(&state.events, i);
790 uint32_t revents = LTTNG_POLL_GETEV(&state.events, i);
791
792 DBG("[rotation-thread] Handling fd (%i) activity (%u)",
793 fd, revents);
794
795 if (fd == handle->thread_quit_pipe) {
796 DBG("[rotation-thread] Quit pipe activity");
797 goto exit;
798 } else if (fd == lttng_pipe_get_readfd(handle->rotation_timer_queue->event_pipe)) {
799 ret = handle_rotate_timer_pipe(revents,
800 handle, &state, handle->rotation_timer_queue);
801 if (ret) {
802 ERR("[rotation-thread] Failed to handle rotation timer pipe event");
803 goto error;
804 }
805 } else if (fd == handle->ust32_consumer ||
806 fd == handle->ust64_consumer ||
807 fd == handle->kernel_consumer) {
808 ret = handle_channel_rotation_pipe(fd,
809 revents, handle, &state);
810 if (ret) {
811 ERR("[rotation-thread] Failed to handle channel rotation pipe");
812 goto error;
813 }
814 } else if (fd == rotate_notification_channel->socket) {
815 ret = handle_notification_channel(fd, revents,
816 handle, &state);
817 if (ret) {
818 ERR("[rotation-thread] Error occured while handling activity on notification channel socket");
819 goto error;
820 }
821 }
822 }
823 }
824 exit:
825 error:
826 DBG("[rotation-thread] Exit");
827 fini_thread_state(&state);
828 health_unregister(health_sessiond);
829 rcu_thread_offline();
830 rcu_unregister_thread();
831 end:
832 return NULL;
833 }
This page took 0.083706 seconds and 4 git commands to generate.