2 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
11 #include <common/hashtable/hashtable.h>
12 #include <common/common.h>
13 #include <common/utils.h>
16 #include "lttng-sessiond.h"
17 #include "health-sessiond.h"
18 #include "testpoint.h"
20 #include "ht-cleanup.h"
22 static int ht_cleanup_quit_pipe
[2] = { -1, -1 };
25 * Check if the ht_cleanup thread quit pipe was triggered.
27 * Return true if it was triggered else false;
29 static bool check_quit_pipe(int fd
, uint32_t events
)
31 return (fd
== ht_cleanup_quit_pipe
[0] && (events
& LPOLLIN
));
34 static int init_pipe(int *pipe_fds
)
40 PERROR("ht_cleanup thread quit pipe");
44 for (i
= 0; i
< 2; i
++) {
45 ret
= fcntl(pipe_fds
[i
], F_SETFD
, FD_CLOEXEC
);
47 PERROR("fcntl ht_cleanup_quit_pipe");
56 * Create a poll set with O_CLOEXEC and add the thread quit pipe to the set.
58 static int set_pollset(struct lttng_poll_event
*events
, size_t size
)
62 ret
= lttng_poll_create(events
, size
, LTTNG_CLOEXEC
);
67 ret
= lttng_poll_add(events
, ht_cleanup_quit_pipe
[0],
73 ret
= lttng_poll_add(events
, the_ht_cleanup_pipe
[0], LPOLLIN
| LPOLLERR
);
75 DBG("[ht-thread] lttng_poll_add error %d.", ret
);
85 static void cleanup_ht_cleanup_thread(void *data
)
87 utils_close_pipe(ht_cleanup_quit_pipe
);
88 utils_close_pipe(the_ht_cleanup_pipe
);
91 static void *thread_ht_cleanup(void *data
)
93 int ret
, i
, pollfd
, err
= -1;
95 uint32_t revents
, nb_fd
;
96 struct lttng_poll_event events
;
98 DBG("[ht-thread] startup.");
100 rcu_register_thread();
103 health_register(the_health_sessiond
, HEALTH_SESSIOND_TYPE_HT_CLEANUP
);
105 if (testpoint(sessiond_thread_ht_cleanup
)) {
106 DBG("[ht-thread] testpoint.");
107 goto error_testpoint
;
110 health_code_update();
112 ret
= set_pollset(&events
, 2);
114 DBG("[ht-thread] sessiond_set_ht_cleanup_thread_pollset error %d.", ret
);
115 goto error_poll_create
;
118 health_code_update();
122 DBG3("[ht-thread] Polling.");
124 ret
= lttng_poll_wait(&events
, -1);
125 DBG3("[ht-thread] Returning from poll on %d fds.",
126 LTTNG_POLL_GETNB(&events
));
130 * Restart interrupted system call.
132 if (errno
== EINTR
) {
139 for (i
= 0; i
< nb_fd
; i
++) {
142 health_code_update();
144 /* Fetch once the poll data */
145 revents
= LTTNG_POLL_GETEV(&events
, i
);
146 pollfd
= LTTNG_POLL_GETFD(&events
, i
);
148 if (pollfd
!= the_ht_cleanup_pipe
[0]) {
152 if (revents
& LPOLLIN
) {
153 /* Get socket from dispatch thread. */
154 size_ret
= lttng_read(the_ht_cleanup_pipe
[0],
156 if (size_ret
< sizeof(ht
)) {
157 PERROR("ht cleanup notify pipe");
160 health_code_update();
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.
167 lttng_ht_destroy(ht
);
169 health_code_update();
172 * Ensure that we never process the quit pipe
173 * event while there is still data available
174 * on the ht clean pipe.
177 } else if (revents
& (LPOLLERR
| LPOLLHUP
| LPOLLRDHUP
)) {
178 ERR("ht cleanup pipe error");
181 ERR("Unexpected poll events %u for sock %d", revents
, pollfd
);
186 for (i
= 0; i
< nb_fd
; i
++) {
187 health_code_update();
189 /* Fetch once the poll data */
190 revents
= LTTNG_POLL_GETEV(&events
, i
);
191 pollfd
= LTTNG_POLL_GETFD(&events
, i
);
194 /* No activity for this FD (poll implementation). */
198 if (pollfd
== the_ht_cleanup_pipe
[0]) {
202 /* Thread quit pipe has been closed. Killing thread. */
203 ret
= check_quit_pipe(pollfd
, revents
);
206 DBG("[ht-cleanup] quit.");
214 lttng_poll_clean(&events
);
217 DBG("[ht-cleanup] Thread terminates.");
220 ERR("Health error occurred in %s", __func__
);
222 health_unregister(the_health_sessiond
);
223 rcu_thread_offline();
224 rcu_unregister_thread();
228 static bool shutdown_ht_cleanup_thread(void *data
)
232 ret
= notify_thread_pipe(ht_cleanup_quit_pipe
[1]);
234 ERR("write error on ht_cleanup quit pipe");
241 struct lttng_thread
*launch_ht_cleanup_thread(void)
244 struct lttng_thread
*thread
;
246 ret
= init_pipe(the_ht_cleanup_pipe
);
251 ret
= init_pipe(ht_cleanup_quit_pipe
);
256 thread
= lttng_thread_create("HT cleanup",
258 shutdown_ht_cleanup_thread
,
259 cleanup_ht_cleanup_thread
,
266 cleanup_ht_cleanup_thread(NULL
);