c190d3b627d0e8bc2ffc079bcc778456d3d22da4
[lttng-tools.git] / src / common / consumer / consumer-timer.c
1 /*
2 * Copyright (C) 2012 Julien Desfossez <julien.desfossez@efficios.com>
3 * Copyright (C) 2012 David Goulet <dgoulet@efficios.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 */
8
9 #define _LGPL_SOURCE
10 #include <assert.h>
11 #include <inttypes.h>
12 #include <signal.h>
13
14 #include <bin/lttng-consumerd/health-consumerd.h>
15 #include <common/common.h>
16 #include <common/compat/endian.h>
17 #include <common/kernel-ctl/kernel-ctl.h>
18 #include <common/kernel-consumer/kernel-consumer.h>
19 #include <common/consumer/consumer-stream.h>
20 #include <common/consumer/consumer-timer.h>
21 #include <common/consumer/consumer-testpoint.h>
22 #include <common/ust-consumer/ust-consumer.h>
23
24 typedef int (*sample_positions_cb)(struct lttng_consumer_stream *stream);
25 typedef int (*get_consumed_cb)(struct lttng_consumer_stream *stream,
26 unsigned long *consumed);
27 typedef int (*get_produced_cb)(struct lttng_consumer_stream *stream,
28 unsigned long *produced);
29 typedef int (*flush_index_cb)(struct lttng_consumer_stream *stream);
30
31 static struct timer_signal_data timer_signal = {
32 .tid = 0,
33 .setup_done = 0,
34 .qs_done = 0,
35 .lock = PTHREAD_MUTEX_INITIALIZER,
36 };
37
38 /*
39 * Set custom signal mask to current thread.
40 */
41 static void setmask(sigset_t *mask)
42 {
43 int ret;
44
45 ret = sigemptyset(mask);
46 if (ret) {
47 PERROR("sigemptyset");
48 }
49 ret = sigaddset(mask, LTTNG_CONSUMER_SIG_SWITCH);
50 if (ret) {
51 PERROR("sigaddset switch");
52 }
53 ret = sigaddset(mask, LTTNG_CONSUMER_SIG_TEARDOWN);
54 if (ret) {
55 PERROR("sigaddset teardown");
56 }
57 ret = sigaddset(mask, LTTNG_CONSUMER_SIG_LIVE);
58 if (ret) {
59 PERROR("sigaddset live");
60 }
61 ret = sigaddset(mask, LTTNG_CONSUMER_SIG_MONITOR);
62 if (ret) {
63 PERROR("sigaddset monitor");
64 }
65 ret = sigaddset(mask, LTTNG_CONSUMER_SIG_EXIT);
66 if (ret) {
67 PERROR("sigaddset exit");
68 }
69 }
70
71 static int channel_monitor_pipe = -1;
72
73 /*
74 * Execute action on a timer switch.
75 *
76 * Beware: metadata_switch_timer() should *never* take a mutex also held
77 * while consumer_timer_switch_stop() is called. It would result in
78 * deadlocks.
79 */
80 static void metadata_switch_timer(struct lttng_consumer_local_data *ctx,
81 siginfo_t *si)
82 {
83 int ret;
84 struct lttng_consumer_channel *channel;
85
86 channel = si->si_value.sival_ptr;
87 assert(channel);
88
89 if (channel->switch_timer_error) {
90 return;
91 }
92
93 DBG("Switch timer for channel %" PRIu64, channel->key);
94 switch (ctx->type) {
95 case LTTNG_CONSUMER32_UST:
96 case LTTNG_CONSUMER64_UST:
97 /*
98 * Locks taken by lttng_ustconsumer_request_metadata():
99 * - metadata_socket_lock
100 * - Calling lttng_ustconsumer_recv_metadata():
101 * - channel->metadata_cache->lock
102 * - Calling consumer_metadata_cache_flushed():
103 * - channel->timer_lock
104 * - channel->metadata_cache->lock
105 *
106 * Ensure that neither consumer_data.lock nor
107 * channel->lock are taken within this function, since
108 * they are held while consumer_timer_switch_stop() is
109 * called.
110 */
111 ret = lttng_ustconsumer_request_metadata(ctx, channel, 1, 1);
112 if (ret < 0) {
113 channel->switch_timer_error = 1;
114 }
115 break;
116 case LTTNG_CONSUMER_KERNEL:
117 case LTTNG_CONSUMER_UNKNOWN:
118 assert(0);
119 break;
120 }
121 }
122
123 static int send_empty_index(struct lttng_consumer_stream *stream, uint64_t ts,
124 uint64_t stream_id)
125 {
126 int ret;
127 struct ctf_packet_index index;
128
129 memset(&index, 0, sizeof(index));
130 index.stream_id = htobe64(stream_id);
131 index.timestamp_end = htobe64(ts);
132 ret = consumer_stream_write_index(stream, &index);
133 if (ret < 0) {
134 goto error;
135 }
136
137 error:
138 return ret;
139 }
140
141 int consumer_flush_kernel_index(struct lttng_consumer_stream *stream)
142 {
143 uint64_t ts, stream_id;
144 int ret;
145
146 ret = kernctl_get_current_timestamp(stream->wait_fd, &ts);
147 if (ret < 0) {
148 ERR("Failed to get the current timestamp");
149 goto end;
150 }
151 ret = kernctl_buffer_flush(stream->wait_fd);
152 if (ret < 0) {
153 ERR("Failed to flush kernel stream");
154 goto end;
155 }
156 ret = kernctl_snapshot(stream->wait_fd);
157 if (ret < 0) {
158 if (ret != -EAGAIN && ret != -ENODATA) {
159 PERROR("live timer kernel snapshot");
160 ret = -1;
161 goto end;
162 }
163 ret = kernctl_get_stream_id(stream->wait_fd, &stream_id);
164 if (ret < 0) {
165 PERROR("kernctl_get_stream_id");
166 goto end;
167 }
168 DBG("Stream %" PRIu64 " empty, sending beacon", stream->key);
169 ret = send_empty_index(stream, ts, stream_id);
170 if (ret < 0) {
171 goto end;
172 }
173 }
174 ret = 0;
175 end:
176 return ret;
177 }
178
179 static int check_stream(struct lttng_consumer_stream *stream,
180 flush_index_cb flush_index)
181 {
182 int ret;
183
184 /*
185 * While holding the stream mutex, try to take a snapshot, if it
186 * succeeds, it means that data is ready to be sent, just let the data
187 * thread handle that. Otherwise, if the snapshot returns EAGAIN, it
188 * means that there is no data to read after the flush, so we can
189 * safely send the empty index.
190 *
191 * Doing a trylock and checking if waiting on metadata if
192 * trylock fails. Bail out of the stream is indeed waiting for
193 * metadata to be pushed. Busy wait on trylock otherwise.
194 */
195 for (;;) {
196 ret = pthread_mutex_trylock(&stream->lock);
197 switch (ret) {
198 case 0:
199 break; /* We have the lock. */
200 case EBUSY:
201 pthread_mutex_lock(&stream->metadata_timer_lock);
202 if (stream->waiting_on_metadata) {
203 ret = 0;
204 stream->missed_metadata_flush = true;
205 pthread_mutex_unlock(&stream->metadata_timer_lock);
206 goto end; /* Bail out. */
207 }
208 pthread_mutex_unlock(&stream->metadata_timer_lock);
209 /* Try again. */
210 caa_cpu_relax();
211 continue;
212 default:
213 ERR("Unexpected pthread_mutex_trylock error %d", ret);
214 ret = -1;
215 goto end;
216 }
217 break;
218 }
219 ret = flush_index(stream);
220 pthread_mutex_unlock(&stream->lock);
221 end:
222 return ret;
223 }
224
225 int consumer_flush_ust_index(struct lttng_consumer_stream *stream)
226 {
227 uint64_t ts, stream_id;
228 int ret;
229
230 ret = cds_lfht_is_node_deleted(&stream->node.node);
231 if (ret) {
232 goto end;
233 }
234
235 ret = lttng_ustconsumer_get_current_timestamp(stream, &ts);
236 if (ret < 0) {
237 ERR("Failed to get the current timestamp");
238 goto end;
239 }
240 lttng_ustconsumer_flush_buffer(stream, 1);
241 ret = lttng_ustconsumer_take_snapshot(stream);
242 if (ret < 0) {
243 if (ret != -EAGAIN) {
244 ERR("Taking UST snapshot");
245 ret = -1;
246 goto end;
247 }
248 ret = lttng_ustconsumer_get_stream_id(stream, &stream_id);
249 if (ret < 0) {
250 PERROR("ustctl_get_stream_id");
251 goto end;
252 }
253 DBG("Stream %" PRIu64 " empty, sending beacon", stream->key);
254 ret = send_empty_index(stream, ts, stream_id);
255 if (ret < 0) {
256 goto end;
257 }
258 }
259 ret = 0;
260 end:
261 return ret;
262 }
263
264 /*
265 * Execute action on a live timer
266 */
267 static void live_timer(struct lttng_consumer_local_data *ctx,
268 siginfo_t *si)
269 {
270 int ret;
271 struct lttng_consumer_channel *channel;
272 struct lttng_consumer_stream *stream;
273 struct lttng_ht_iter iter;
274 const struct lttng_ht *ht = consumer_data.stream_per_chan_id_ht;
275 const flush_index_cb flush_index =
276 ctx->type == LTTNG_CONSUMER_KERNEL ?
277 consumer_flush_kernel_index :
278 consumer_flush_ust_index;
279
280 channel = si->si_value.sival_ptr;
281 assert(channel);
282
283 if (channel->switch_timer_error) {
284 goto error;
285 }
286
287 DBG("Live timer for channel %" PRIu64, channel->key);
288
289 rcu_read_lock();
290 cds_lfht_for_each_entry_duplicate(ht->ht,
291 ht->hash_fct(&channel->key, lttng_ht_seed),
292 ht->match_fct, &channel->key, &iter.iter,
293 stream, node_channel_id.node) {
294 ret = check_stream(stream, flush_index);
295 if (ret < 0) {
296 goto error_unlock;
297 }
298 }
299
300 error_unlock:
301 rcu_read_unlock();
302
303 error:
304 return;
305 }
306
307 static
308 void consumer_timer_signal_thread_qs(unsigned int signr)
309 {
310 sigset_t pending_set;
311 int ret;
312
313 /*
314 * We need to be the only thread interacting with the thread
315 * that manages signals for teardown synchronization.
316 */
317 pthread_mutex_lock(&timer_signal.lock);
318
319 /* Ensure we don't have any signal queued for this channel. */
320 for (;;) {
321 ret = sigemptyset(&pending_set);
322 if (ret == -1) {
323 PERROR("sigemptyset");
324 }
325 ret = sigpending(&pending_set);
326 if (ret == -1) {
327 PERROR("sigpending");
328 }
329 if (!sigismember(&pending_set, signr)) {
330 break;
331 }
332 caa_cpu_relax();
333 }
334
335 /*
336 * From this point, no new signal handler will be fired that would try to
337 * access "chan". However, we still need to wait for any currently
338 * executing handler to complete.
339 */
340 cmm_smp_mb();
341 CMM_STORE_SHARED(timer_signal.qs_done, 0);
342 cmm_smp_mb();
343
344 /*
345 * Kill with LTTNG_CONSUMER_SIG_TEARDOWN, so signal management thread wakes
346 * up.
347 */
348 kill(getpid(), LTTNG_CONSUMER_SIG_TEARDOWN);
349
350 while (!CMM_LOAD_SHARED(timer_signal.qs_done)) {
351 caa_cpu_relax();
352 }
353 cmm_smp_mb();
354
355 pthread_mutex_unlock(&timer_signal.lock);
356 }
357
358 /*
359 * Start a timer channel timer which will fire at a given interval
360 * (timer_interval_us)and fire a given signal (signal).
361 *
362 * Returns a negative value on error, 0 if a timer was created, and
363 * a positive value if no timer was created (not an error).
364 */
365 static
366 int consumer_channel_timer_start(timer_t *timer_id,
367 struct lttng_consumer_channel *channel,
368 unsigned int timer_interval_us, int signal)
369 {
370 int ret = 0, delete_ret;
371 struct sigevent sev;
372 struct itimerspec its;
373
374 assert(channel);
375 assert(channel->key);
376
377 if (timer_interval_us == 0) {
378 /* No creation needed; not an error. */
379 ret = 1;
380 goto end;
381 }
382
383 sev.sigev_notify = SIGEV_SIGNAL;
384 sev.sigev_signo = signal;
385 sev.sigev_value.sival_ptr = channel;
386 ret = timer_create(CLOCKID, &sev, timer_id);
387 if (ret == -1) {
388 PERROR("timer_create");
389 goto end;
390 }
391
392 its.it_value.tv_sec = timer_interval_us / 1000000;
393 its.it_value.tv_nsec = (timer_interval_us % 1000000) * 1000;
394 its.it_interval.tv_sec = its.it_value.tv_sec;
395 its.it_interval.tv_nsec = its.it_value.tv_nsec;
396
397 ret = timer_settime(*timer_id, 0, &its, NULL);
398 if (ret == -1) {
399 PERROR("timer_settime");
400 goto error_destroy_timer;
401 }
402 end:
403 return ret;
404 error_destroy_timer:
405 delete_ret = timer_delete(*timer_id);
406 if (delete_ret == -1) {
407 PERROR("timer_delete");
408 }
409 goto end;
410 }
411
412 static
413 int consumer_channel_timer_stop(timer_t *timer_id, int signal)
414 {
415 int ret = 0;
416
417 ret = timer_delete(*timer_id);
418 if (ret == -1) {
419 PERROR("timer_delete");
420 goto end;
421 }
422
423 consumer_timer_signal_thread_qs(signal);
424 *timer_id = 0;
425 end:
426 return ret;
427 }
428
429 /*
430 * Set the channel's switch timer.
431 */
432 void consumer_timer_switch_start(struct lttng_consumer_channel *channel,
433 unsigned int switch_timer_interval_us)
434 {
435 int ret;
436
437 assert(channel);
438 assert(channel->key);
439
440 ret = consumer_channel_timer_start(&channel->switch_timer, channel,
441 switch_timer_interval_us, LTTNG_CONSUMER_SIG_SWITCH);
442
443 channel->switch_timer_enabled = !!(ret == 0);
444 }
445
446 /*
447 * Stop and delete the channel's switch timer.
448 */
449 void consumer_timer_switch_stop(struct lttng_consumer_channel *channel)
450 {
451 int ret;
452
453 assert(channel);
454
455 ret = consumer_channel_timer_stop(&channel->switch_timer,
456 LTTNG_CONSUMER_SIG_SWITCH);
457 if (ret == -1) {
458 ERR("Failed to stop switch timer");
459 }
460
461 channel->switch_timer_enabled = 0;
462 }
463
464 /*
465 * Set the channel's live timer.
466 */
467 void consumer_timer_live_start(struct lttng_consumer_channel *channel,
468 unsigned int live_timer_interval_us)
469 {
470 int ret;
471
472 assert(channel);
473 assert(channel->key);
474
475 ret = consumer_channel_timer_start(&channel->live_timer, channel,
476 live_timer_interval_us, LTTNG_CONSUMER_SIG_LIVE);
477
478 channel->live_timer_enabled = !!(ret == 0);
479 }
480
481 /*
482 * Stop and delete the channel's live timer.
483 */
484 void consumer_timer_live_stop(struct lttng_consumer_channel *channel)
485 {
486 int ret;
487
488 assert(channel);
489
490 ret = consumer_channel_timer_stop(&channel->live_timer,
491 LTTNG_CONSUMER_SIG_LIVE);
492 if (ret == -1) {
493 ERR("Failed to stop live timer");
494 }
495
496 channel->live_timer_enabled = 0;
497 }
498
499 /*
500 * Set the channel's monitoring timer.
501 *
502 * Returns a negative value on error, 0 if a timer was created, and
503 * a positive value if no timer was created (not an error).
504 */
505 int consumer_timer_monitor_start(struct lttng_consumer_channel *channel,
506 unsigned int monitor_timer_interval_us)
507 {
508 int ret;
509
510 assert(channel);
511 assert(channel->key);
512 assert(!channel->monitor_timer_enabled);
513
514 ret = consumer_channel_timer_start(&channel->monitor_timer, channel,
515 monitor_timer_interval_us, LTTNG_CONSUMER_SIG_MONITOR);
516 channel->monitor_timer_enabled = !!(ret == 0);
517 return ret;
518 }
519
520 /*
521 * Stop and delete the channel's monitoring timer.
522 */
523 int consumer_timer_monitor_stop(struct lttng_consumer_channel *channel)
524 {
525 int ret;
526
527 assert(channel);
528 assert(channel->monitor_timer_enabled);
529
530 ret = consumer_channel_timer_stop(&channel->monitor_timer,
531 LTTNG_CONSUMER_SIG_MONITOR);
532 if (ret == -1) {
533 ERR("Failed to stop live timer");
534 goto end;
535 }
536
537 channel->monitor_timer_enabled = 0;
538 end:
539 return ret;
540 }
541
542 /*
543 * Block the RT signals for the entire process. It must be called from the
544 * consumer main before creating the threads
545 */
546 int consumer_signal_init(void)
547 {
548 int ret;
549 sigset_t mask;
550
551 /* Block signal for entire process, so only our thread processes it. */
552 setmask(&mask);
553 ret = pthread_sigmask(SIG_BLOCK, &mask, NULL);
554 if (ret) {
555 errno = ret;
556 PERROR("pthread_sigmask");
557 return -1;
558 }
559 return 0;
560 }
561
562 static
563 int sample_channel_positions(struct lttng_consumer_channel *channel,
564 uint64_t *_highest_use, uint64_t *_lowest_use, uint64_t *_total_consumed,
565 sample_positions_cb sample, get_consumed_cb get_consumed,
566 get_produced_cb get_produced)
567 {
568 int ret = 0;
569 struct lttng_ht_iter iter;
570 struct lttng_consumer_stream *stream;
571 bool empty_channel = true;
572 uint64_t high = 0, low = UINT64_MAX;
573 struct lttng_ht *ht = consumer_data.stream_per_chan_id_ht;
574
575 *_total_consumed = 0;
576
577 rcu_read_lock();
578
579 cds_lfht_for_each_entry_duplicate(ht->ht,
580 ht->hash_fct(&channel->key, lttng_ht_seed),
581 ht->match_fct, &channel->key,
582 &iter.iter, stream, node_channel_id.node) {
583 unsigned long produced, consumed, usage;
584
585 empty_channel = false;
586
587 pthread_mutex_lock(&stream->lock);
588 if (cds_lfht_is_node_deleted(&stream->node.node)) {
589 goto next;
590 }
591
592 ret = sample(stream);
593 if (ret) {
594 ERR("Failed to take buffer position snapshot in monitor timer (ret = %d)", ret);
595 pthread_mutex_unlock(&stream->lock);
596 goto end;
597 }
598 ret = get_consumed(stream, &consumed);
599 if (ret) {
600 ERR("Failed to get buffer consumed position in monitor timer");
601 pthread_mutex_unlock(&stream->lock);
602 goto end;
603 }
604 ret = get_produced(stream, &produced);
605 if (ret) {
606 ERR("Failed to get buffer produced position in monitor timer");
607 pthread_mutex_unlock(&stream->lock);
608 goto end;
609 }
610
611 usage = produced - consumed;
612 high = (usage > high) ? usage : high;
613 low = (usage < low) ? usage : low;
614
615 /*
616 * We don't use consumed here for 2 reasons:
617 * - output_written takes into account the padding written in the
618 * tracefiles when we stop the session;
619 * - the consumed position is not the accurate representation of what
620 * was extracted from a buffer in overwrite mode.
621 */
622 *_total_consumed += stream->output_written;
623 next:
624 pthread_mutex_unlock(&stream->lock);
625 }
626
627 *_highest_use = high;
628 *_lowest_use = low;
629 end:
630 rcu_read_unlock();
631 if (empty_channel) {
632 ret = -1;
633 }
634 return ret;
635 }
636
637 /*
638 * Execute action on a monitor timer.
639 */
640 static
641 void monitor_timer(struct lttng_consumer_channel *channel)
642 {
643 int ret;
644 int channel_monitor_pipe =
645 consumer_timer_thread_get_channel_monitor_pipe();
646 struct lttcomm_consumer_channel_monitor_msg msg = {
647 .key = channel->key,
648 };
649 sample_positions_cb sample;
650 get_consumed_cb get_consumed;
651 get_produced_cb get_produced;
652 uint64_t lowest = 0, highest = 0, total_consumed = 0;
653
654 assert(channel);
655
656 if (channel_monitor_pipe < 0) {
657 return;
658 }
659
660 switch (consumer_data.type) {
661 case LTTNG_CONSUMER_KERNEL:
662 sample = lttng_kconsumer_sample_snapshot_positions;
663 get_consumed = lttng_kconsumer_get_consumed_snapshot;
664 get_produced = lttng_kconsumer_get_produced_snapshot;
665 break;
666 case LTTNG_CONSUMER32_UST:
667 case LTTNG_CONSUMER64_UST:
668 sample = lttng_ustconsumer_sample_snapshot_positions;
669 get_consumed = lttng_ustconsumer_get_consumed_snapshot;
670 get_produced = lttng_ustconsumer_get_produced_snapshot;
671 break;
672 default:
673 abort();
674 }
675
676 ret = sample_channel_positions(channel, &highest, &lowest,
677 &total_consumed, sample, get_consumed, get_produced);
678 if (ret) {
679 return;
680 }
681 msg.highest = highest;
682 msg.lowest = lowest;
683 msg.total_consumed = total_consumed;
684
685 /*
686 * Writes performed here are assumed to be atomic which is only
687 * guaranteed for sizes < than PIPE_BUF.
688 */
689 assert(sizeof(msg) <= PIPE_BUF);
690
691 do {
692 ret = write(channel_monitor_pipe, &msg, sizeof(msg));
693 } while (ret == -1 && errno == EINTR);
694 if (ret == -1) {
695 if (errno == EAGAIN) {
696 /* Not an error, the sample is merely dropped. */
697 DBG("Channel monitor pipe is full; dropping sample for channel key = %"PRIu64,
698 channel->key);
699 } else {
700 PERROR("write to the channel monitor pipe");
701 }
702 } else {
703 DBG("Sent channel monitoring sample for channel key %" PRIu64
704 ", (highest = %" PRIu64 ", lowest = %"PRIu64")",
705 channel->key, msg.highest, msg.lowest);
706 }
707 }
708
709 int consumer_timer_thread_get_channel_monitor_pipe(void)
710 {
711 return uatomic_read(&channel_monitor_pipe);
712 }
713
714 int consumer_timer_thread_set_channel_monitor_pipe(int fd)
715 {
716 int ret;
717
718 ret = uatomic_cmpxchg(&channel_monitor_pipe, -1, fd);
719 if (ret != -1) {
720 ret = -1;
721 goto end;
722 }
723 ret = 0;
724 end:
725 return ret;
726 }
727
728 /*
729 * This thread is the sighandler for signals LTTNG_CONSUMER_SIG_SWITCH,
730 * LTTNG_CONSUMER_SIG_TEARDOWN, LTTNG_CONSUMER_SIG_LIVE, and
731 * LTTNG_CONSUMER_SIG_MONITOR, LTTNG_CONSUMER_SIG_EXIT.
732 */
733 void *consumer_timer_thread(void *data)
734 {
735 int signr;
736 sigset_t mask;
737 siginfo_t info;
738 struct lttng_consumer_local_data *ctx = data;
739
740 rcu_register_thread();
741
742 health_register(health_consumerd, HEALTH_CONSUMERD_TYPE_METADATA_TIMER);
743
744 if (testpoint(consumerd_thread_metadata_timer)) {
745 goto error_testpoint;
746 }
747
748 health_code_update();
749
750 /* Only self thread will receive signal mask. */
751 setmask(&mask);
752 CMM_STORE_SHARED(timer_signal.tid, pthread_self());
753
754 while (1) {
755 health_code_update();
756
757 health_poll_entry();
758 signr = sigwaitinfo(&mask, &info);
759 health_poll_exit();
760
761 /*
762 * NOTE: cascading conditions are used instead of a switch case
763 * since the use of SIGRTMIN in the definition of the signals'
764 * values prevents the reduction to an integer constant.
765 */
766 if (signr == -1) {
767 if (errno != EINTR) {
768 PERROR("sigwaitinfo");
769 }
770 continue;
771 } else if (signr == LTTNG_CONSUMER_SIG_SWITCH) {
772 metadata_switch_timer(ctx, &info);
773 } else if (signr == LTTNG_CONSUMER_SIG_TEARDOWN) {
774 cmm_smp_mb();
775 CMM_STORE_SHARED(timer_signal.qs_done, 1);
776 cmm_smp_mb();
777 DBG("Signal timer metadata thread teardown");
778 } else if (signr == LTTNG_CONSUMER_SIG_LIVE) {
779 live_timer(ctx, &info);
780 } else if (signr == LTTNG_CONSUMER_SIG_MONITOR) {
781 struct lttng_consumer_channel *channel;
782
783 channel = info.si_value.sival_ptr;
784 monitor_timer(channel);
785 } else if (signr == LTTNG_CONSUMER_SIG_EXIT) {
786 assert(CMM_LOAD_SHARED(consumer_quit));
787 goto end;
788 } else {
789 ERR("Unexpected signal %d\n", info.si_signo);
790 }
791 }
792
793 error_testpoint:
794 /* Only reached in testpoint error */
795 health_error();
796 end:
797 health_unregister(health_consumerd);
798 rcu_unregister_thread();
799 return NULL;
800 }
This page took 0.043325 seconds and 3 git commands to generate.