SoW-2020-0002: Trace Hit Counters: trigger error reporting integration
[lttng-tools.git] / src / bin / lttng-sessiond / manage-apps.c
CommitLineData
7649924e 1/*
ab5be9fa
MJ
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>
7649924e 5 *
ab5be9fa 6 * SPDX-License-Identifier: GPL-2.0-only
7649924e 7 *
7649924e
JG
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
16struct thread_notifiers {
17 struct lttng_pipe *quit_pipe;
18 int apps_cmd_pipe_read_fd;
19};
20
21static void cleanup_application_management_thread(void *data)
22{
23 struct thread_notifiers *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 */
42static 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 = 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(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
7649924e
JG
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
177exit:
178error:
179 lttng_poll_clean(&events);
180error_poll_create:
181error_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(health_sessiond);
194 DBG("Application communication apps thread cleanup complete");
195 rcu_thread_offline();
196 rcu_unregister_thread();
197 return NULL;
198}
199
200static bool shutdown_application_management_thread(void *data)
201{
202 struct thread_notifiers *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
208bool 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
7649924e
JG
214 notifiers = zmalloc(sizeof(*notifiers));
215 if (!notifiers) {
21fa020e
JG
216 goto error_alloc;
217 }
218 quit_pipe = lttng_pipe_open(FD_CLOEXEC);
219 if (!quit_pipe) {
7649924e
JG
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;
236error:
237 cleanup_application_management_thread(notifiers);
21fa020e 238error_alloc:
7649924e
JG
239 return false;
240}
This page took 0.045664 seconds and 5 git commands to generate.