Tests: event notifier error counters
[lttng-tools.git] / src / bin / lttng-sessiond / thread-utils.c
1 /*
2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-only
7 *
8 */
9
10 #include "lttng-sessiond.h"
11 #include "utils.h"
12 #include <common/utils.h>
13 #include <pthread.h>
14
15 /*
16 * Quit pipe for all threads. This permits a single cancellation point
17 * for all threads when receiving an event on the pipe.
18 */
19 static int thread_quit_pipe[2] = { -1, -1 };
20
21 /*
22 * Init thread quit pipe.
23 *
24 * Return -1 on error or 0 if all pipes are created.
25 */
26 static int __init_thread_quit_pipe(int *a_pipe)
27 {
28 int ret, i;
29
30 ret = pipe(a_pipe);
31 if (ret < 0) {
32 PERROR("thread quit pipe");
33 goto error;
34 }
35
36 for (i = 0; i < 2; i++) {
37 ret = fcntl(a_pipe[i], F_SETFD, FD_CLOEXEC);
38 if (ret < 0) {
39 PERROR("fcntl");
40 goto error;
41 }
42 }
43
44 error:
45 return ret;
46 }
47
48 int sessiond_init_thread_quit_pipe(void)
49 {
50 return __init_thread_quit_pipe(thread_quit_pipe);
51 }
52
53 int sessiond_check_thread_quit_pipe(int fd, uint32_t events)
54 {
55 return (fd == thread_quit_pipe[0] && (events & LPOLLIN));
56 }
57
58 /*
59 * Wait for a notification on the quit pipe (with a timeout).
60 *
61 * A timeout value of -1U means no timeout.
62 *
63 * Returns 1 if the caller should quit, 0 if the timeout was reached, and
64 * -1 if an error was encountered.
65 */
66 int sessiond_wait_for_quit_pipe(int timeout_ms)
67 {
68 int ret;
69 struct lttng_poll_event events;
70
71 ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
72 if (ret < 0) {
73 PERROR("Failed to initialize poll/epoll set");
74 ret = -1;
75 goto end;
76 }
77 ret = lttng_poll_add(&events, thread_quit_pipe[0], LPOLLIN | LPOLLERR);
78 if (ret < 0) {
79 PERROR("Failed to add file descriptor to poll/epoll set");
80 ret = -1;
81 goto end_clean_poll;
82 }
83 ret = lttng_poll_wait(&events, timeout_ms);
84 if (ret > 0) {
85 /* Should quit. */
86 ret = 1;
87 } else if (ret < 0 && errno != EINTR) {
88 /* Unknown error. */
89 PERROR("Failed to epoll()/poll() thread quit pipe");
90 ret = -1;
91 } else {
92 /* Timeout reached. */
93 ret = 0;
94 }
95 end_clean_poll:
96 lttng_poll_clean(&events);
97 end:
98 return ret;
99 }
100
101 int sessiond_notify_quit_pipe(void)
102 {
103 return notify_thread_pipe(thread_quit_pipe[1]);
104 }
105
106 void sessiond_close_quit_pipe(void)
107 {
108 utils_close_pipe(thread_quit_pipe);
109 }
110
111 static
112 int __sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size,
113 int *a_pipe)
114 {
115 int ret;
116
117 assert(events);
118
119 ret = lttng_poll_create(events, size, LTTNG_CLOEXEC);
120 if (ret < 0) {
121 goto error;
122 }
123
124 /* Add quit pipe */
125 ret = lttng_poll_add(events, a_pipe[0], LPOLLIN | LPOLLERR);
126 if (ret < 0) {
127 goto error;
128 }
129
130 return 0;
131
132 error:
133 return ret;
134 }
135
136 /*
137 * Create a poll set with O_CLOEXEC and add the thread quit pipe to the set.
138 */
139 int sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size)
140 {
141 return __sessiond_set_thread_pollset(events, size, thread_quit_pipe);
142 }
This page took 0.033486 seconds and 4 git commands to generate.