liblttng-ctl: use export list to define exported symbols
[lttng-tools.git] / src / bin / lttng-sessiond / notify-apps.c
CommitLineData
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
DG
9
10#include <common/common.h>
11#include <common/utils.h>
12
13#include "fd-limit.h"
14#include "lttng-sessiond.h"
f9d2ba6a 15#include "notify-apps.h"
8782cc74 16#include "health-sessiond.h"
9ad42ec1 17#include "testpoint.h"
971a61c6
JG
18#include "utils.h"
19#include "thread.h"
20
21struct thread_notifiers {
22 struct lttng_pipe *quit_pipe;
23 int apps_cmd_notify_pipe_read_fd;
24};
d0b96690
DG
25
26/*
27 * This thread manage application notify communication.
28 */
971a61c6 29static void *thread_application_notification(void *data)
d0b96690 30{
380e8d6f 31 int i, ret, pollfd, err = -1;
6cd525e8 32 ssize_t size_ret;
d0b96690
DG
33 uint32_t revents, nb_fd;
34 struct lttng_poll_event events;
971a61c6
JG
35 struct thread_notifiers *notifiers = data;
36 const int quit_pipe_read_fd = lttng_pipe_get_readfd(notifiers->quit_pipe);
d0b96690
DG
37
38 DBG("[ust-thread] Manage application notify command");
39
40 rcu_register_thread();
41 rcu_thread_online();
42
412d7227
SM
43 health_register(the_health_sessiond,
44 HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY);
380e8d6f 45
9ad42ec1
MD
46 if (testpoint(sessiond_thread_app_manage_notify)) {
47 goto error_testpoint;
48 }
49
380e8d6f
MD
50 health_code_update();
51
971a61c6 52 ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
d0b96690
DG
53 if (ret < 0) {
54 goto error_poll_create;
55 }
56
57 /* Add notify pipe to the pollset. */
971a61c6 58 ret = lttng_poll_add(&events, notifiers->apps_cmd_notify_pipe_read_fd,
03e43155 59 LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP);
d0b96690
DG
60 if (ret < 0) {
61 goto error;
62 }
63
971a61c6
JG
64 ret = lttng_poll_add(&events, quit_pipe_read_fd,
65 LPOLLIN | LPOLLERR);
66 if (ret < 0) {
67 goto error;
68 }
69
380e8d6f
MD
70 health_code_update();
71
d0b96690 72 while (1) {
7fa2082e 73 DBG3("[ust-thread] Manage notify polling");
d0b96690
DG
74
75 /* Inifinite blocking call, waiting for transmission */
76restart:
380e8d6f 77 health_poll_entry();
d0b96690 78 ret = lttng_poll_wait(&events, -1);
7fa2082e
MD
79 DBG3("[ust-thread] Manage notify return from poll on %d fds",
80 LTTNG_POLL_GETNB(&events));
380e8d6f 81 health_poll_exit();
d0b96690
DG
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++) {
380e8d6f
MD
95 health_code_update();
96
d0b96690
DG
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. */
971a61c6 102 if (pollfd == quit_pipe_read_fd) {
380e8d6f 103 err = 0;
d0b96690 104 goto exit;
971a61c6
JG
105 } else if (pollfd == notifiers->apps_cmd_notify_pipe_read_fd) {
106 /* Inspect the apps cmd pipe */
d0b96690
DG
107 int sock;
108
03e43155
MD
109 if (revents & LPOLLIN) {
110 /* Get socket from dispatch thread. */
971a61c6 111 size_ret = lttng_read(notifiers->apps_cmd_notify_pipe_read_fd,
03e43155
MD
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)) {
d0b96690
DG
135 ERR("Apps notify command pipe error");
136 goto error;
03e43155
MD
137 } else {
138 ERR("Unexpected poll events %u for sock %d", revents, pollfd);
d0b96690
DG
139 goto error;
140 }
d0b96690
DG
141 } else {
142 /*
143 * At this point, we know that a registered application
144 * triggered the event.
145 */
03e43155
MD
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)) {
d0b96690
DG
159 /* Removing from the poll set */
160 ret = lttng_poll_del(&events, pollfd);
161 if (ret < 0) {
162 goto error;
163 }
164
d88aee68
DG
165 /* The socket is closed after a grace period here. */
166 ust_app_notify_sock_unregister(pollfd);
d0b96690 167 } else {
03e43155
MD
168 ERR("Unexpected poll events %u for sock %d", revents, pollfd);
169 goto error;
d0b96690 170 }
380e8d6f 171 health_code_update();
d0b96690
DG
172 }
173 }
174 }
175
176exit:
177error:
178 lttng_poll_clean(&events);
179error_poll_create:
9ad42ec1 180error_testpoint:
971a61c6 181
d0b96690 182 DBG("Application notify communication apps thread cleanup complete");
380e8d6f
MD
183 if (err) {
184 health_error();
185 ERR("Health error occurred in %s", __func__);
186 }
412d7227 187 health_unregister(the_health_sessiond);
d0b96690
DG
188 rcu_thread_offline();
189 rcu_unregister_thread();
190 return NULL;
191}
971a61c6
JG
192
193static bool shutdown_application_notification_thread(void *data)
194{
195 struct thread_notifiers *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
201static void cleanup_application_notification_thread(void *data)
202{
203 struct thread_notifiers *notifiers = data;
204
205 lttng_pipe_destroy(notifiers->quit_pipe);
206 free(notifiers);
207}
208
209bool 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 = zmalloc(sizeof(*notifiers));
216 if (!notifiers) {
21fa020e 217 goto error_alloc;
971a61c6
JG
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;
237error:
238 cleanup_application_notification_thread(notifiers);
21fa020e 239error_alloc:
971a61c6
JG
240 return false;
241}
This page took 0.068374 seconds and 4 git commands to generate.