Tests: add missing kernel test cases to make check target
[lttng-tools.git] / src / bin / lttng-sessiond / manage-apps.cpp
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 "manage-apps.h"
11 #include "testpoint.h"
12 #include "health-sessiond.h"
13 #include "utils.h"
14 #include "thread.h"
15
16 struct thread_notifiers {
17 struct lttng_pipe *quit_pipe;
18 int apps_cmd_pipe_read_fd;
19 };
20
21 static void cleanup_application_management_thread(void *data)
22 {
23 struct thread_notifiers *notifiers = (thread_notifiers *) data;
24
25 lttng_pipe_destroy(notifiers->quit_pipe);
26 free(notifiers);
27 }
28
29 /*
30 * This thread receives application command sockets (FDs) on the
31 * apps_cmd_pipe and waits (polls) on them until they are closed
32 * or an error occurs.
33 *
34 * At that point, it flushes the data (tracing and metadata) associated
35 * with this application and tears down ust app sessions and other
36 * associated data structures through ust_app_unregister().
37 *
38 * Note that this thread never sends commands to the applications
39 * through the command sockets; it merely listens for hang-ups
40 * and errors on those sockets and cleans-up as they occur.
41 */
42 static void *thread_application_management(void *data)
43 {
44 int i, ret, pollfd, err = -1;
45 ssize_t size_ret;
46 uint32_t revents, nb_fd;
47 struct lttng_poll_event events;
48 struct thread_notifiers *notifiers = (thread_notifiers *) data;
49 const int quit_pipe_read_fd = lttng_pipe_get_readfd(
50 notifiers->quit_pipe);
51
52 DBG("[thread] Manage application started");
53
54 rcu_register_thread();
55 rcu_thread_online();
56
57 health_register(the_health_sessiond, HEALTH_SESSIOND_TYPE_APP_MANAGE);
58
59 if (testpoint(sessiond_thread_manage_apps)) {
60 goto error_testpoint;
61 }
62
63 health_code_update();
64
65 ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
66 if (ret < 0) {
67 goto error_poll_create;
68 }
69
70 ret = lttng_poll_add(&events, notifiers->apps_cmd_pipe_read_fd,
71 LPOLLIN | LPOLLRDHUP);
72 if (ret < 0) {
73 goto error;
74 }
75
76 ret = lttng_poll_add(&events, quit_pipe_read_fd, LPOLLIN | LPOLLERR);
77 if (ret < 0) {
78 goto error;
79 }
80
81 if (testpoint(sessiond_thread_manage_apps_before_loop)) {
82 goto error;
83 }
84
85 health_code_update();
86
87 while (1) {
88 DBG("Apps thread polling");
89
90 /* Inifinite blocking call, waiting for transmission */
91 restart:
92 health_poll_entry();
93 ret = lttng_poll_wait(&events, -1);
94 DBG("Apps thread return from poll on %d fds",
95 LTTNG_POLL_GETNB(&events));
96 health_poll_exit();
97 if (ret < 0) {
98 /*
99 * Restart interrupted system call.
100 */
101 if (errno == EINTR) {
102 goto restart;
103 }
104 goto error;
105 }
106
107 nb_fd = ret;
108
109 for (i = 0; i < nb_fd; i++) {
110 /* Fetch once the poll data */
111 revents = LTTNG_POLL_GETEV(&events, i);
112 pollfd = LTTNG_POLL_GETFD(&events, i);
113
114 health_code_update();
115
116 if (pollfd == quit_pipe_read_fd) {
117 err = 0;
118 goto exit;
119 } else if (pollfd == notifiers->apps_cmd_pipe_read_fd) {
120 /* Inspect the apps cmd pipe */
121 if (revents & LPOLLIN) {
122 int sock;
123
124 /* Empty pipe */
125 size_ret = lttng_read(
126 notifiers->apps_cmd_pipe_read_fd,
127 &sock, sizeof(sock));
128 if (size_ret < sizeof(sock)) {
129 PERROR("read apps cmd pipe");
130 goto error;
131 }
132
133 health_code_update();
134
135 /*
136 * Since this is a command socket (write then read),
137 * we only monitor the error events of the socket.
138 */
139 ret = lttng_poll_add(&events, sock,
140 LPOLLERR | LPOLLHUP | LPOLLRDHUP);
141 if (ret < 0) {
142 goto error;
143 }
144
145 DBG("Apps with sock %d added to poll set", sock);
146 } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
147 ERR("Apps command pipe error");
148 goto error;
149 } else {
150 ERR("Unknown poll events %u for sock %d", revents, pollfd);
151 goto error;
152 }
153 } else {
154 /*
155 * At this point, we know that a registered application made
156 * the event at poll_wait.
157 */
158 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 /* Socket closed on remote end. */
166 ust_app_unregister(pollfd);
167 } else {
168 ERR("Unexpected poll events %u for sock %d", revents, pollfd);
169 goto error;
170 }
171 }
172
173 health_code_update();
174 }
175 }
176
177 exit:
178 error:
179 lttng_poll_clean(&events);
180 error_poll_create:
181 error_testpoint:
182
183 /*
184 * We don't clean the UST app hash table here since already registered
185 * applications can still be controlled so let them be until the session
186 * daemon dies or the applications stop.
187 */
188
189 if (err) {
190 health_error();
191 ERR("Health error occurred in %s", __func__);
192 }
193 health_unregister(the_health_sessiond);
194 DBG("Application communication apps thread cleanup complete");
195 rcu_thread_offline();
196 rcu_unregister_thread();
197 return NULL;
198 }
199
200 static bool shutdown_application_management_thread(void *data)
201 {
202 struct thread_notifiers *notifiers = (thread_notifiers *) data;
203 const int write_fd = lttng_pipe_get_writefd(notifiers->quit_pipe);
204
205 return notify_thread_pipe(write_fd) == 1;
206 }
207
208 bool launch_application_management_thread(int apps_cmd_pipe_read_fd)
209 {
210 struct lttng_pipe *quit_pipe;
211 struct thread_notifiers *notifiers = NULL;
212 struct lttng_thread *thread;
213
214 notifiers = (thread_notifiers *) zmalloc(sizeof(*notifiers));
215 if (!notifiers) {
216 goto error_alloc;
217 }
218 quit_pipe = lttng_pipe_open(FD_CLOEXEC);
219 if (!quit_pipe) {
220 goto error;
221 }
222 notifiers->quit_pipe = quit_pipe;
223 notifiers->apps_cmd_pipe_read_fd = apps_cmd_pipe_read_fd;
224
225 thread = lttng_thread_create("UST application management",
226 thread_application_management,
227 shutdown_application_management_thread,
228 cleanup_application_management_thread,
229 notifiers);
230 if (!thread) {
231 goto error;
232 }
233
234 lttng_thread_put(thread);
235 return true;
236 error:
237 cleanup_application_management_thread(notifiers);
238 error_alloc:
239 return false;
240 }
This page took 0.035274 seconds and 4 git commands to generate.