2 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
10 #include <common/hashtable/hashtable.h>
11 #include <common/common.h>
12 #include <common/utils.h>
15 #include "lttng-sessiond.h"
16 #include "health-sessiond.h"
17 #include "testpoint.h"
19 #include "ht-cleanup.h"
21 static int ht_cleanup_quit_pipe
[2] = { -1, -1 };
24 * Check if the ht_cleanup thread quit pipe was triggered.
26 * Return true if it was triggered else false;
28 static bool check_quit_pipe(int fd
, uint32_t events
)
30 return (fd
== ht_cleanup_quit_pipe
[0] && (events
& LPOLLIN
));
33 static int init_pipe(int *pipe_fds
)
39 PERROR("ht_cleanup thread quit pipe");
43 for (i
= 0; i
< 2; i
++) {
44 ret
= fcntl(pipe_fds
[i
], F_SETFD
, FD_CLOEXEC
);
46 PERROR("fcntl ht_cleanup_quit_pipe");
55 * Create a poll set with O_CLOEXEC and add the thread quit pipe to the set.
57 static int set_pollset(struct lttng_poll_event
*events
, size_t size
)
61 ret
= lttng_poll_create(events
, size
, LTTNG_CLOEXEC
);
66 ret
= lttng_poll_add(events
, ht_cleanup_quit_pipe
[0],
72 ret
= lttng_poll_add(events
, the_ht_cleanup_pipe
[0], LPOLLIN
| LPOLLERR
);
74 DBG("lttng_poll_add error %d.", ret
);
84 static void cleanup_ht_cleanup_thread(void *data
)
86 utils_close_pipe(ht_cleanup_quit_pipe
);
87 utils_close_pipe(the_ht_cleanup_pipe
);
90 static void *thread_ht_cleanup(void *data
)
92 int ret
, i
, pollfd
, err
= -1;
94 uint32_t revents
, nb_fd
;
95 struct lttng_poll_event events
;
99 rcu_register_thread();
102 health_register(the_health_sessiond
, HEALTH_SESSIOND_TYPE_HT_CLEANUP
);
104 if (testpoint(sessiond_thread_ht_cleanup
)) {
106 goto error_testpoint
;
109 health_code_update();
111 ret
= set_pollset(&events
, 2);
113 DBG("sessiond_set_ht_cleanup_thread_pollset error %d.", ret
);
114 goto error_poll_create
;
117 health_code_update();
123 ret
= lttng_poll_wait(&events
, -1);
124 DBG3("Returning from poll on %d fds.",
125 LTTNG_POLL_GETNB(&events
));
129 * Restart interrupted system call.
131 if (errno
== EINTR
) {
138 for (i
= 0; i
< nb_fd
; i
++) {
141 health_code_update();
143 /* Fetch once the poll data */
144 revents
= LTTNG_POLL_GETEV(&events
, i
);
145 pollfd
= LTTNG_POLL_GETFD(&events
, i
);
147 if (pollfd
!= the_ht_cleanup_pipe
[0]) {
151 if (revents
& LPOLLIN
) {
152 /* Get socket from dispatch thread. */
153 size_ret
= lttng_read(the_ht_cleanup_pipe
[0],
155 if (size_ret
< sizeof(ht
)) {
156 PERROR("ht cleanup notify pipe");
159 health_code_update();
161 * The whole point of this thread is to call
162 * lttng_ht_destroy from a context that is NOT:
163 * 1) a read-side RCU lock,
164 * 2) a call_rcu thread.
166 lttng_ht_destroy(ht
);
168 health_code_update();
171 * Ensure that we never process the quit pipe
172 * event while there is still data available
173 * on the ht clean pipe.
176 } else if (revents
& (LPOLLERR
| LPOLLHUP
| LPOLLRDHUP
)) {
177 ERR("ht cleanup pipe error");
180 ERR("Unexpected poll events %u for sock %d", revents
, pollfd
);
185 for (i
= 0; i
< nb_fd
; i
++) {
186 health_code_update();
188 /* Fetch once the poll data */
189 revents
= LTTNG_POLL_GETEV(&events
, i
);
190 pollfd
= LTTNG_POLL_GETFD(&events
, i
);
193 /* No activity for this FD (poll implementation). */
197 if (pollfd
== the_ht_cleanup_pipe
[0]) {
201 /* Thread quit pipe has been closed. Killing thread. */
202 ret
= check_quit_pipe(pollfd
, revents
);
205 DBG("[ht-cleanup] quit.");
213 lttng_poll_clean(&events
);
216 DBG("[ht-cleanup] Thread terminates.");
219 ERR("Health error occurred in %s", __func__
);
221 health_unregister(the_health_sessiond
);
222 rcu_thread_offline();
223 rcu_unregister_thread();
227 static bool shutdown_ht_cleanup_thread(void *data
)
231 ret
= notify_thread_pipe(ht_cleanup_quit_pipe
[1]);
233 ERR("write error on ht_cleanup quit pipe");
240 struct lttng_thread
*launch_ht_cleanup_thread(void)
243 struct lttng_thread
*thread
;
245 ret
= init_pipe(the_ht_cleanup_pipe
);
250 ret
= init_pipe(ht_cleanup_quit_pipe
);
255 thread
= lttng_thread_create("HT cleanup",
257 shutdown_ht_cleanup_thread
,
258 cleanup_ht_cleanup_thread
,
265 cleanup_ht_cleanup_thread(NULL
);