2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <lttng/trigger/trigger.h>
20 #include <common/error.h>
21 #include <common/config/session-config.h>
22 #include <common/defaults.h>
23 #include <common/utils.h>
24 #include <sys/eventfd.h>
27 #include "notification-thread.h"
28 #include "lttng-sessiond.h"
29 #include "health-sessiond.h"
32 * Destroy the thread data previously created by the init function.
34 void notification_destroy_data(struct notification_thread_data
*data
)
42 if (data
->cmd_queue
.event_fd
< 0) {
45 ret
= close(data
->cmd_queue
.event_fd
);
47 PERROR("close notification command queue event_fd");
50 /* TODO: purge queue and mark commands as cancelled. */
56 * Initialize the thread's data. This MUST be called before the notification
59 struct notification_thread_data
*notification_init_data(void)
61 struct notification_thread_data
*data
;
63 data
= zmalloc(sizeof(*data
));
68 data
->cmd_queue
.event_fd
= eventfd(0, EFD_CLOEXEC
);
69 if (data
->cmd_queue
.event_fd
< 0) {
70 PERROR("eventfd notification command queue");
73 cds_wfcq_init(&data
->cmd_queue
.head
, &data
->cmd_queue
.tail
);
77 notification_destroy_data(data
);
82 char *get_notification_channel_sock_path(void)
85 bool is_root
= !getuid();
88 sock_path
= zmalloc(LTTNG_PATH_MAX
);
94 ret
= snprintf(sock_path
, LTTNG_PATH_MAX
,
95 DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK
);
100 char *home_path
= utils_get_home_dir();
103 ERR("Can't get HOME directory for socket creation");
108 ret
= snprintf(sock_path
, LTTNG_PATH_MAX
,
109 DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK
,
123 void notification_channel_socket_destroy(int fd
)
126 char *sock_path
= get_notification_channel_sock_path();
128 DBG("[notification-thread] Destroying notification channel socket");
131 ret
= unlink(sock_path
);
134 PERROR("unlink notification channel socket");
140 PERROR("close notification channel socket");
145 int notification_channel_socket_create(void)
148 char *sock_path
= get_notification_channel_sock_path();
150 DBG("[notification-thread] Creating notification channel UNIX socket at %s",
153 ret
= lttcomm_create_unix_sock(sock_path
);
155 ERR("[notification-thread] Failed to create notification socket");
160 ret
= chmod(sock_path
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
162 ERR("Set file permissions failed: %s", sock_path
);
163 PERROR("chmod notification channel socket");
167 DBG("[notification-thread] Notification channel UNIX socket created (fd = %i)",
172 if (fd
>= 0 && close(fd
) < 0) {
173 PERROR("close notification channel socket");
180 * This thread services notification channel clients and received notifications
181 * from various lttng-sessiond components over a command queue.
183 void *thread_notification(void *data
)
186 struct lttng_poll_event events
;
187 int notification_channel_socket
;
188 struct notification_thread_data
*ctx
= data
;
190 DBG("[notification-thread] Started notification thread");
193 ERR("[notification-thread] Invalid thread context provided");
197 rcu_register_thread();
200 health_register(health_sessiond
, HEALTH_SESSIOND_TYPE_NOTIFICATION
);
201 health_code_update();
203 notification_channel_socket
= notification_channel_socket_create();
206 * Create pollset with size 2, quit pipe and notification channel
207 * socket, and the command queue event fd.
209 ret
= sessiond_set_thread_pollset(&events
, 3);
211 goto error_poll_create
;
214 /* Add notification channel socket to poll set. */
215 ret
= lttng_poll_add(&events
, notification_channel_socket
,
216 LPOLLIN
| LPOLLERR
| LPOLLHUP
| LPOLLRDHUP
);
218 ERR("[notification-thread] Failed to add notification channel socket to pollset");
222 ret
= lttng_poll_add(&events
, ctx
->cmd_queue
.event_fd
,
225 ERR("[notification-thread] Failed to add notification command queue event fd to pollset");
229 DBG("[notification-thread] Listening on notification channel socket");
230 ret
= lttcomm_listen_unix_sock(notification_channel_socket
);
232 ERR("[notification-thread] Listen failed on notification channel socket");
240 DBG("[notification-thread] Entering poll wait");
241 ret
= lttng_poll_wait(&events
, -1);
242 DBG("[notification-thread] Poll wait returned (%i)", ret
);
246 * Restart interrupted system call.
248 if (errno
== EINTR
) {
251 ERR("[notification-thread] Error encountered during lttng_poll_wait (%i)", ret
);
256 for (i
= 0; i
< fd_count
; i
++) {
257 int fd
= LTTNG_POLL_GETFD(&events
, i
);
258 uint32_t revents
= LTTNG_POLL_GETEV(&events
, i
);
260 /* Thread quit pipe has been closed. Killing thread. */
261 if (sessiond_check_thread_quit_pipe(fd
, revents
)) {
262 DBG("[notification-thread] Quit pipe signaled, exiting.");
270 lttng_poll_clean(&events
);
272 notification_channel_socket_destroy(notification_channel_socket
);
273 health_unregister(health_sessiond
);
274 rcu_thread_offline();
275 rcu_unregister_thread();