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