Fix: common: local_attr might leak
[lttng-tools.git] / src / bin / lttng-sessiond / ht-cleanup.c
CommitLineData
0b2dc8df 1/*
ab5be9fa 2 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
0b2dc8df 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
0b2dc8df 5 *
0b2dc8df
MD
6 */
7
6c1c0768 8#define _LGPL_SOURCE
0b2dc8df
MD
9#include <assert.h>
10
11#include <common/hashtable/hashtable.h>
12#include <common/common.h>
13#include <common/utils.h>
5e97de00 14#include <pthread.h>
0b2dc8df
MD
15
16#include "lttng-sessiond.h"
8782cc74 17#include "health-sessiond.h"
9ad42ec1 18#include "testpoint.h"
5e97de00 19#include "utils.h"
a3707772 20#include "ht-cleanup.h"
0b2dc8df 21
a3707772 22static int ht_cleanup_quit_pipe[2] = { -1, -1 };
5e97de00
JG
23
24/*
25 * Check if the ht_cleanup thread quit pipe was triggered.
26 *
27 * Return true if it was triggered else false;
28 */
29static bool check_quit_pipe(int fd, uint32_t events)
30{
31 return (fd == ht_cleanup_quit_pipe[0] && (events & LPOLLIN));
32}
33
34static int init_pipe(int *pipe_fds)
35{
36 int ret, i;
37
38 ret = pipe(pipe_fds);
39 if (ret < 0) {
40 PERROR("ht_cleanup thread quit pipe");
41 goto error;
42 }
43
44 for (i = 0; i < 2; i++) {
45 ret = fcntl(pipe_fds[i], F_SETFD, FD_CLOEXEC);
46 if (ret < 0) {
47 PERROR("fcntl ht_cleanup_quit_pipe");
48 goto error;
49 }
50 }
51error:
52 return ret;
53}
54
55/*
56 * Create a poll set with O_CLOEXEC and add the thread quit pipe to the set.
57 */
58static int set_pollset(struct lttng_poll_event *events, size_t size)
59{
60 int ret;
61
62 ret = lttng_poll_create(events, size, LTTNG_CLOEXEC);
63 if (ret < 0) {
64 goto error;
65 }
66
67 ret = lttng_poll_add(events, ht_cleanup_quit_pipe[0],
68 LPOLLIN | LPOLLERR);
69 if (ret < 0) {
70 goto error;
71 }
72
412d7227 73 ret = lttng_poll_add(events, the_ht_cleanup_pipe[0], LPOLLIN | LPOLLERR);
5e97de00 74 if (ret < 0) {
f91c3842 75 DBG("lttng_poll_add error %d.", ret);
5e97de00
JG
76 goto error;
77 }
78
79 return 0;
80
81error:
82 return ret;
83}
84
a3707772
JG
85static void cleanup_ht_cleanup_thread(void *data)
86{
87 utils_close_pipe(ht_cleanup_quit_pipe);
412d7227 88 utils_close_pipe(the_ht_cleanup_pipe);
a3707772
JG
89}
90
5e97de00 91static void *thread_ht_cleanup(void *data)
0b2dc8df
MD
92{
93 int ret, i, pollfd, err = -1;
6cd525e8 94 ssize_t size_ret;
0b2dc8df
MD
95 uint32_t revents, nb_fd;
96 struct lttng_poll_event events;
97
f91c3842 98 DBG("startup.");
0b2dc8df
MD
99
100 rcu_register_thread();
101 rcu_thread_online();
102
412d7227 103 health_register(the_health_sessiond, HEALTH_SESSIOND_TYPE_HT_CLEANUP);
0b2dc8df 104
9ad42ec1 105 if (testpoint(sessiond_thread_ht_cleanup)) {
f91c3842 106 DBG("testpoint.");
9ad42ec1
MD
107 goto error_testpoint;
108 }
109
0b2dc8df
MD
110 health_code_update();
111
5e97de00 112 ret = set_pollset(&events, 2);
0b2dc8df 113 if (ret < 0) {
f91c3842 114 DBG("sessiond_set_ht_cleanup_thread_pollset error %d.", ret);
0b2dc8df
MD
115 goto error_poll_create;
116 }
117
0b2dc8df
MD
118 health_code_update();
119
120 while (1) {
df119599 121 restart:
f91c3842 122 DBG3("Polling.");
0b2dc8df
MD
123 health_poll_entry();
124 ret = lttng_poll_wait(&events, -1);
f91c3842 125 DBG3("Returning from poll on %d fds.",
7fa2082e 126 LTTNG_POLL_GETNB(&events));
0b2dc8df
MD
127 health_poll_exit();
128 if (ret < 0) {
129 /*
130 * Restart interrupted system call.
131 */
132 if (errno == EINTR) {
5e97de00 133 continue;
0b2dc8df
MD
134 }
135 goto error;
136 }
137
138 nb_fd = ret;
0b2dc8df
MD
139 for (i = 0; i < nb_fd; i++) {
140 struct lttng_ht *ht;
141
142 health_code_update();
143
144 /* Fetch once the poll data */
145 revents = LTTNG_POLL_GETEV(&events, i);
146 pollfd = LTTNG_POLL_GETFD(&events, i);
147
412d7227 148 if (pollfd != the_ht_cleanup_pipe[0]) {
4a15001e 149 continue;
0b2dc8df 150 }
0b2dc8df 151
03e43155
MD
152 if (revents & LPOLLIN) {
153 /* Get socket from dispatch thread. */
412d7227
SM
154 size_ret = lttng_read(the_ht_cleanup_pipe[0],
155 &ht, sizeof(ht));
03e43155
MD
156 if (size_ret < sizeof(ht)) {
157 PERROR("ht cleanup notify pipe");
158 goto error;
159 }
160 health_code_update();
161 /*
162 * The whole point of this thread is to call
163 * lttng_ht_destroy from a context that is NOT:
164 * 1) a read-side RCU lock,
165 * 2) a call_rcu thread.
166 */
167 lttng_ht_destroy(ht);
168
169 health_code_update();
df119599
JG
170
171 /*
172 * Ensure that we never process the quit pipe
173 * event while there is still data available
174 * on the ht clean pipe.
175 */
176 goto restart;
03e43155 177 } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
0b2dc8df
MD
178 ERR("ht cleanup pipe error");
179 goto error;
03e43155
MD
180 } else {
181 ERR("Unexpected poll events %u for sock %d", revents, pollfd);
0b2dc8df
MD
182 goto error;
183 }
0b2dc8df 184 }
4a15001e 185
4a15001e
MD
186 for (i = 0; i < nb_fd; i++) {
187 health_code_update();
188
189 /* Fetch once the poll data */
190 revents = LTTNG_POLL_GETEV(&events, i);
191 pollfd = LTTNG_POLL_GETFD(&events, i);
192
fd20dac9
MD
193 if (!revents) {
194 /* No activity for this FD (poll implementation). */
195 continue;
196 }
197
412d7227 198 if (pollfd == the_ht_cleanup_pipe[0]) {
4a15001e
MD
199 continue;
200 }
201
202 /* Thread quit pipe has been closed. Killing thread. */
5e97de00 203 ret = check_quit_pipe(pollfd, revents);
4a15001e
MD
204 if (ret) {
205 err = 0;
74588b4d 206 DBG("[ht-cleanup] quit.");
4a15001e
MD
207 goto exit;
208 }
209 }
0b2dc8df
MD
210 }
211
212exit:
213error:
214 lttng_poll_clean(&events);
215error_poll_create:
9ad42ec1 216error_testpoint:
4a15001e 217 DBG("[ht-cleanup] Thread terminates.");
0b2dc8df
MD
218 if (err) {
219 health_error();
220 ERR("Health error occurred in %s", __func__);
221 }
412d7227 222 health_unregister(the_health_sessiond);
0b2dc8df
MD
223 rcu_thread_offline();
224 rcu_unregister_thread();
225 return NULL;
226}
5e97de00 227
a3707772
JG
228static bool shutdown_ht_cleanup_thread(void *data)
229{
230 int ret;
231
232 ret = notify_thread_pipe(ht_cleanup_quit_pipe[1]);
233 if (ret < 0) {
234 ERR("write error on ht_cleanup quit pipe");
235 goto end;
236 }
237end:
238 return ret;
239}
240
241struct lttng_thread *launch_ht_cleanup_thread(void)
5e97de00
JG
242{
243 int ret;
a3707772 244 struct lttng_thread *thread;
5e97de00 245
412d7227 246 ret = init_pipe(the_ht_cleanup_pipe);
5e97de00
JG
247 if (ret) {
248 goto error;
249 }
250
77fc2bc2 251 ret = init_pipe(ht_cleanup_quit_pipe);
5e97de00 252 if (ret) {
a3707772 253 goto error;
5e97de00
JG
254 }
255
a3707772
JG
256 thread = lttng_thread_create("HT cleanup",
257 thread_ht_cleanup,
258 shutdown_ht_cleanup_thread,
259 cleanup_ht_cleanup_thread,
1a1a34b4 260 NULL);
a3707772 261 if (!thread) {
a3707772 262 goto error;
5e97de00 263 }
a3707772 264 return thread;
5e97de00 265error:
a3707772
JG
266 cleanup_ht_cleanup_thread(NULL);
267 return NULL;
5e97de00 268}
This page took 0.066866 seconds and 4 git commands to generate.