Commit | Line | Data |
---|---|---|
d0b96690 | 1 | /* |
ab5be9fa | 2 | * Copyright (C) 2013 David Goulet <dgoulet@efficios.com> |
d0b96690 | 3 | * |
ab5be9fa | 4 | * SPDX-License-Identifier: GPL-2.0-only |
d0b96690 | 5 | * |
d0b96690 | 6 | */ |
890d8fe4 | 7 | |
6c1c0768 | 8 | #define _LGPL_SOURCE |
d0b96690 | 9 | |
c9e313bc | 10 | #include "fd-limit.hpp" |
28ab034a | 11 | #include "health-sessiond.hpp" |
c9e313bc SM |
12 | #include "lttng-sessiond.hpp" |
13 | #include "notify-apps.hpp" | |
c9e313bc | 14 | #include "testpoint.hpp" |
c9e313bc | 15 | #include "thread.hpp" |
28ab034a JG |
16 | #include "utils.hpp" |
17 | ||
18 | #include <common/common.hpp> | |
19 | #include <common/utils.hpp> | |
971a61c6 | 20 | |
671e39d7 MJ |
21 | #include <fcntl.h> |
22 | ||
f1494934 | 23 | namespace { |
971a61c6 JG |
24 | struct thread_notifiers { |
25 | struct lttng_pipe *quit_pipe; | |
26 | int apps_cmd_notify_pipe_read_fd; | |
27 | }; | |
f1494934 | 28 | } /* namespace */ |
d0b96690 DG |
29 | |
30 | /* | |
31 | * This thread manage application notify communication. | |
32 | */ | |
971a61c6 | 33 | static void *thread_application_notification(void *data) |
d0b96690 | 34 | { |
8a00688e | 35 | int i, ret, err = -1; |
6cd525e8 | 36 | ssize_t size_ret; |
8a00688e | 37 | uint32_t nb_fd; |
d0b96690 | 38 | struct lttng_poll_event events; |
7966af57 | 39 | struct thread_notifiers *notifiers = (thread_notifiers *) data; |
8a00688e | 40 | const auto thread_quit_pipe_fd = lttng_pipe_get_readfd(notifiers->quit_pipe); |
d0b96690 DG |
41 | |
42 | DBG("[ust-thread] Manage application notify command"); | |
43 | ||
44 | rcu_register_thread(); | |
45 | rcu_thread_online(); | |
46 | ||
28ab034a | 47 | health_register(the_health_sessiond, HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY); |
380e8d6f | 48 | |
9ad42ec1 MD |
49 | if (testpoint(sessiond_thread_app_manage_notify)) { |
50 | goto error_testpoint; | |
51 | } | |
52 | ||
380e8d6f MD |
53 | health_code_update(); |
54 | ||
971a61c6 | 55 | ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC); |
d0b96690 DG |
56 | if (ret < 0) { |
57 | goto error_poll_create; | |
58 | } | |
59 | ||
60 | /* Add notify pipe to the pollset. */ | |
28ab034a JG |
61 | ret = lttng_poll_add( |
62 | &events, notifiers->apps_cmd_notify_pipe_read_fd, LPOLLIN | LPOLLRDHUP); | |
d0b96690 DG |
63 | if (ret < 0) { |
64 | goto error; | |
65 | } | |
66 | ||
1524f98c | 67 | ret = lttng_poll_add(&events, thread_quit_pipe_fd, LPOLLIN); |
971a61c6 JG |
68 | if (ret < 0) { |
69 | goto error; | |
70 | } | |
71 | ||
380e8d6f MD |
72 | health_code_update(); |
73 | ||
cd9adb8b | 74 | while (true) { |
7fa2082e | 75 | DBG3("[ust-thread] Manage notify polling"); |
d0b96690 DG |
76 | |
77 | /* Inifinite blocking call, waiting for transmission */ | |
28ab034a | 78 | restart: |
380e8d6f | 79 | health_poll_entry(); |
d0b96690 | 80 | ret = lttng_poll_wait(&events, -1); |
7fa2082e | 81 | DBG3("[ust-thread] Manage notify return from poll on %d fds", |
28ab034a | 82 | LTTNG_POLL_GETNB(&events)); |
380e8d6f | 83 | health_poll_exit(); |
d0b96690 DG |
84 | if (ret < 0) { |
85 | /* | |
86 | * Restart interrupted system call. | |
87 | */ | |
88 | if (errno == EINTR) { | |
89 | goto restart; | |
90 | } | |
91 | goto error; | |
92 | } | |
93 | ||
94 | nb_fd = ret; | |
95 | ||
96 | for (i = 0; i < nb_fd; i++) { | |
380e8d6f MD |
97 | health_code_update(); |
98 | ||
d0b96690 | 99 | /* Fetch once the poll data */ |
8a00688e MJ |
100 | const auto revents = LTTNG_POLL_GETEV(&events, i); |
101 | const auto pollfd = LTTNG_POLL_GETFD(&events, i); | |
d0b96690 | 102 | |
8a00688e MJ |
103 | /* Activity on thread quit pipe, exiting. */ |
104 | if (pollfd == thread_quit_pipe_fd) { | |
105 | DBG("Activity on thread quit pipe"); | |
380e8d6f | 106 | err = 0; |
d0b96690 | 107 | goto exit; |
8a00688e MJ |
108 | } |
109 | ||
110 | if (pollfd == notifiers->apps_cmd_notify_pipe_read_fd) { | |
971a61c6 | 111 | /* Inspect the apps cmd pipe */ |
d0b96690 DG |
112 | int sock; |
113 | ||
03e43155 MD |
114 | if (revents & LPOLLIN) { |
115 | /* Get socket from dispatch thread. */ | |
28ab034a JG |
116 | size_ret = |
117 | lttng_read(notifiers->apps_cmd_notify_pipe_read_fd, | |
118 | &sock, | |
119 | sizeof(sock)); | |
03e43155 MD |
120 | if (size_ret < sizeof(sock)) { |
121 | PERROR("read apps notify pipe"); | |
122 | goto error; | |
123 | } | |
124 | health_code_update(); | |
125 | ||
1524f98c | 126 | ret = lttng_poll_add(&events, sock, LPOLLIN | LPOLLRDHUP); |
03e43155 MD |
127 | if (ret < 0) { |
128 | /* | |
28ab034a JG |
129 | * It's possible we've reached the max poll fd |
130 | * allowed. Let's close the socket but continue | |
131 | * normal execution. | |
03e43155 MD |
132 | */ |
133 | ret = close(sock); | |
134 | if (ret) { | |
135 | PERROR("close notify socket %d", sock); | |
136 | } | |
137 | lttng_fd_put(LTTNG_FD_APPS, 1); | |
138 | continue; | |
139 | } | |
140 | DBG3("UST thread notify added sock %d to pollset", sock); | |
141 | } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { | |
d0b96690 DG |
142 | ERR("Apps notify command pipe error"); |
143 | goto error; | |
03e43155 | 144 | } else { |
28ab034a JG |
145 | ERR("Unexpected poll events %u for sock %d", |
146 | revents, | |
147 | pollfd); | |
d0b96690 DG |
148 | goto error; |
149 | } | |
d0b96690 DG |
150 | } else { |
151 | /* | |
152 | * At this point, we know that a registered application | |
153 | * triggered the event. | |
154 | */ | |
03e43155 MD |
155 | if (revents & (LPOLLIN | LPOLLPRI)) { |
156 | ret = ust_app_recv_notify(pollfd); | |
157 | if (ret < 0) { | |
158 | /* Removing from the poll set */ | |
159 | ret = lttng_poll_del(&events, pollfd); | |
160 | if (ret < 0) { | |
161 | goto error; | |
162 | } | |
163 | ||
28ab034a JG |
164 | /* The socket is closed after a grace period here. |
165 | */ | |
03e43155 MD |
166 | ust_app_notify_sock_unregister(pollfd); |
167 | } | |
168 | } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { | |
d0b96690 DG |
169 | /* Removing from the poll set */ |
170 | ret = lttng_poll_del(&events, pollfd); | |
171 | if (ret < 0) { | |
172 | goto error; | |
173 | } | |
174 | ||
d88aee68 DG |
175 | /* The socket is closed after a grace period here. */ |
176 | ust_app_notify_sock_unregister(pollfd); | |
d0b96690 | 177 | } else { |
28ab034a JG |
178 | ERR("Unexpected poll events %u for sock %d", |
179 | revents, | |
180 | pollfd); | |
03e43155 | 181 | goto error; |
d0b96690 | 182 | } |
380e8d6f | 183 | health_code_update(); |
d0b96690 DG |
184 | } |
185 | } | |
186 | } | |
187 | ||
188 | exit: | |
189 | error: | |
190 | lttng_poll_clean(&events); | |
191 | error_poll_create: | |
9ad42ec1 | 192 | error_testpoint: |
971a61c6 | 193 | |
d0b96690 | 194 | DBG("Application notify communication apps thread cleanup complete"); |
380e8d6f MD |
195 | if (err) { |
196 | health_error(); | |
197 | ERR("Health error occurred in %s", __func__); | |
198 | } | |
412d7227 | 199 | health_unregister(the_health_sessiond); |
d0b96690 DG |
200 | rcu_thread_offline(); |
201 | rcu_unregister_thread(); | |
cd9adb8b | 202 | return nullptr; |
d0b96690 | 203 | } |
971a61c6 JG |
204 | |
205 | static bool shutdown_application_notification_thread(void *data) | |
206 | { | |
7966af57 | 207 | struct thread_notifiers *notifiers = (thread_notifiers *) data; |
971a61c6 JG |
208 | const int write_fd = lttng_pipe_get_writefd(notifiers->quit_pipe); |
209 | ||
210 | return notify_thread_pipe(write_fd) == 1; | |
211 | } | |
212 | ||
213 | static void cleanup_application_notification_thread(void *data) | |
214 | { | |
7966af57 | 215 | struct thread_notifiers *notifiers = (thread_notifiers *) data; |
971a61c6 JG |
216 | |
217 | lttng_pipe_destroy(notifiers->quit_pipe); | |
218 | free(notifiers); | |
219 | } | |
220 | ||
221 | bool launch_application_notification_thread(int apps_cmd_notify_pipe_read_fd) | |
222 | { | |
223 | struct lttng_thread *thread; | |
224 | struct thread_notifiers *notifiers; | |
225 | struct lttng_pipe *quit_pipe; | |
226 | ||
64803277 | 227 | notifiers = zmalloc<thread_notifiers>(); |
971a61c6 | 228 | if (!notifiers) { |
21fa020e | 229 | goto error_alloc; |
971a61c6 JG |
230 | } |
231 | notifiers->apps_cmd_notify_pipe_read_fd = apps_cmd_notify_pipe_read_fd; | |
232 | ||
233 | quit_pipe = lttng_pipe_open(FD_CLOEXEC); | |
234 | if (!quit_pipe) { | |
235 | goto error; | |
236 | } | |
237 | notifiers->quit_pipe = quit_pipe; | |
238 | ||
239 | thread = lttng_thread_create("Application notification", | |
28ab034a JG |
240 | thread_application_notification, |
241 | shutdown_application_notification_thread, | |
242 | cleanup_application_notification_thread, | |
243 | notifiers); | |
971a61c6 JG |
244 | if (!thread) { |
245 | goto error; | |
246 | } | |
247 | lttng_thread_put(thread); | |
248 | return true; | |
249 | error: | |
250 | cleanup_application_notification_thread(notifiers); | |
21fa020e | 251 | error_alloc: |
971a61c6 JG |
252 | return false; |
253 | } |