Fix: sessiond: double socket close on allocation failure
[lttng-tools.git] / src / bin / lttng-sessiond / register.c
... / ...
CommitLineData
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * 2013 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2 only,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include <stddef.h>
21#include <stdlib.h>
22#include <urcu.h>
23#include <common/futex.h>
24#include <common/macros.h>
25#include <common/utils.h>
26#include <sys/stat.h>
27
28#include "register.h"
29#include "lttng-sessiond.h"
30#include "testpoint.h"
31#include "health-sessiond.h"
32#include "fd-limit.h"
33#include "shm.h"
34#include "utils.h"
35#include "thread.h"
36
37struct thread_state {
38 struct lttng_pipe *quit_pipe;
39 struct ust_cmd_queue *ust_cmd_queue;
40 sem_t ready;
41 bool running;
42 int application_socket;
43};
44
45/*
46 * Creates the application socket.
47 */
48static int create_application_socket(void)
49{
50 int ret = 0;
51 int apps_sock;
52 const mode_t old_umask = umask(0);
53
54 /* Create the application unix socket */
55 apps_sock = lttcomm_create_unix_sock(config.apps_unix_sock_path.value);
56 if (apps_sock < 0) {
57 ERR("Create unix sock failed: %s", config.apps_unix_sock_path.value);
58 ret = -1;
59 goto end;
60 }
61
62 /* Set the cloexec flag */
63 ret = utils_set_fd_cloexec(apps_sock);
64 if (ret < 0) {
65 ERR("Unable to set CLOEXEC flag to the app Unix socket (fd: %d). "
66 "Continuing but note that the consumer daemon will have a "
67 "reference to this socket on exec()", apps_sock);
68 }
69
70 /* File permission MUST be 666 */
71 ret = chmod(config.apps_unix_sock_path.value,
72 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
73 if (ret < 0) {
74 PERROR("Set file permissions failed on %s",
75 config.apps_unix_sock_path.value);
76 goto error_close_socket;
77 }
78
79 DBG3("Session daemon application socket created (fd = %d) ", apps_sock);
80 ret = apps_sock;
81end:
82 umask(old_umask);
83 return ret;
84error_close_socket:
85 if (close(apps_sock)) {
86 PERROR("Failed to close application socket in error path");
87 }
88 apps_sock = -1;
89 ret = -1;
90 goto end;
91}
92
93/*
94 * Notify UST applications using the shm mmap futex.
95 */
96static int notify_ust_apps(int active, bool is_root)
97{
98 char *wait_shm_mmap;
99
100 DBG("Notifying applications of session daemon state: %d", active);
101
102 /* See shm.c for this call implying mmap, shm and futex calls */
103 wait_shm_mmap = shm_ust_get_mmap(config.wait_shm_path.value, is_root);
104 if (wait_shm_mmap == NULL) {
105 goto error;
106 }
107
108 /* Wake waiting process */
109 futex_wait_update((int32_t *) wait_shm_mmap, active);
110
111 /* Apps notified successfully */
112 return 0;
113
114error:
115 return -1;
116}
117
118static void cleanup_application_registration_thread(void *data)
119{
120 struct thread_state *thread_state = data;
121
122 if (!data) {
123 return;
124 }
125
126 lttng_pipe_destroy(thread_state->quit_pipe);
127 free(thread_state);
128}
129
130static void set_thread_status(struct thread_state *thread_state, bool running)
131{
132 DBG("Marking application registration thread's state as %s", running ? "running" : "error");
133 thread_state->running = running;
134 sem_post(&thread_state->ready);
135}
136
137static bool wait_thread_status(struct thread_state *thread_state)
138{
139 DBG("Waiting for application registration thread to be ready");
140 sem_wait(&thread_state->ready);
141 if (thread_state->running) {
142 DBG("Application registration thread is ready");
143 } else {
144 ERR("Initialization of application registration thread failed");
145 }
146
147 return thread_state->running;
148}
149
150static void thread_init_cleanup(void *data)
151{
152 struct thread_state *thread_state = data;
153
154 set_thread_status(thread_state, false);
155}
156
157/*
158 * This thread manage application registration.
159 */
160static void *thread_application_registration(void *data)
161{
162 int sock = -1, i, ret, pollfd, err = -1;
163 uint32_t revents, nb_fd;
164 struct lttng_poll_event events;
165 /*
166 * Gets allocated in this thread, enqueued to a global queue, dequeued
167 * and freed in the manage apps thread.
168 */
169 struct ust_command *ust_cmd = NULL;
170 const bool is_root = (getuid() == 0);
171 struct thread_state *thread_state = data;
172 const int application_socket = thread_state->application_socket;
173 const int quit_pipe_read_fd = lttng_pipe_get_readfd(
174 thread_state->quit_pipe);
175
176 DBG("[thread] Manage application registration started");
177
178 pthread_cleanup_push(thread_init_cleanup, NULL);
179 health_register(health_sessiond, HEALTH_SESSIOND_TYPE_APP_REG);
180
181 ret = lttcomm_listen_unix_sock(application_socket);
182 if (ret < 0) {
183 goto error_listen;
184 }
185
186 if (testpoint(sessiond_thread_registration_apps)) {
187 goto error_create_poll;
188 }
189
190 /*
191 * Pass 2 as size here for the thread quit pipe and apps_sock. Nothing
192 * more will be added to this poll set.
193 */
194 ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
195 if (ret < 0) {
196 goto error_create_poll;
197 }
198
199 /* Add the application registration socket */
200 ret = lttng_poll_add(&events, application_socket, LPOLLIN | LPOLLRDHUP);
201 if (ret < 0) {
202 goto error_poll_add;
203 }
204
205 /* Add the application registration socket */
206 ret = lttng_poll_add(&events, quit_pipe_read_fd, LPOLLIN | LPOLLRDHUP);
207 if (ret < 0) {
208 goto error_poll_add;
209 }
210
211 set_thread_status(thread_state, true);
212 pthread_cleanup_pop(0);
213
214 while (1) {
215 DBG("Accepting application registration");
216
217 /* Inifinite blocking call, waiting for transmission */
218 restart:
219 health_poll_entry();
220 ret = lttng_poll_wait(&events, -1);
221 health_poll_exit();
222 if (ret < 0) {
223 /*
224 * Restart interrupted system call.
225 */
226 if (errno == EINTR) {
227 goto restart;
228 }
229 goto error;
230 }
231
232 nb_fd = ret;
233
234 for (i = 0; i < nb_fd; i++) {
235 health_code_update();
236
237 /* Fetch once the poll data */
238 revents = LTTNG_POLL_GETEV(&events, i);
239 pollfd = LTTNG_POLL_GETFD(&events, i);
240
241 /* Thread quit pipe has been closed. Killing thread. */
242 if (pollfd == quit_pipe_read_fd) {
243 err = 0;
244 goto exit;
245 } else {
246 /* Event on the registration socket */
247 if (revents & LPOLLIN) {
248 sock = lttcomm_accept_unix_sock(application_socket);
249 if (sock < 0) {
250 goto error;
251 }
252
253 /*
254 * Set socket timeout for both receiving and ending.
255 * app_socket_timeout is in seconds, whereas
256 * lttcomm_setsockopt_rcv_timeout and
257 * lttcomm_setsockopt_snd_timeout expect msec as
258 * parameter.
259 */
260 if (config.app_socket_timeout >= 0) {
261 (void) lttcomm_setsockopt_rcv_timeout(sock,
262 config.app_socket_timeout * 1000);
263 (void) lttcomm_setsockopt_snd_timeout(sock,
264 config.app_socket_timeout * 1000);
265 }
266
267 /*
268 * Set the CLOEXEC flag. Return code is useless because
269 * either way, the show must go on.
270 */
271 (void) utils_set_fd_cloexec(sock);
272
273 /* Create UST registration command for enqueuing */
274 ust_cmd = zmalloc(sizeof(struct ust_command));
275 if (ust_cmd == NULL) {
276 PERROR("ust command zmalloc");
277 ret = close(sock);
278 if (ret) {
279 PERROR("close");
280 }
281 sock = -1;
282 goto error;
283 }
284
285 /*
286 * Using message-based transmissions to ensure we don't
287 * have to deal with partially received messages.
288 */
289 ret = lttng_fd_get(LTTNG_FD_APPS, 1);
290 if (ret < 0) {
291 ERR("Exhausted file descriptors allowed for applications.");
292 free(ust_cmd);
293 ret = close(sock);
294 if (ret) {
295 PERROR("close");
296 }
297 sock = -1;
298 continue;
299 }
300
301 health_code_update();
302 ret = ust_app_recv_registration(sock, &ust_cmd->reg_msg);
303 if (ret < 0) {
304 free(ust_cmd);
305 /* Close socket of the application. */
306 ret = close(sock);
307 if (ret) {
308 PERROR("close");
309 }
310 lttng_fd_put(LTTNG_FD_APPS, 1);
311 sock = -1;
312 continue;
313 }
314 health_code_update();
315
316 ust_cmd->sock = sock;
317 sock = -1;
318
319 DBG("UST registration received with pid:%d ppid:%d uid:%d"
320 " gid:%d sock:%d name:%s (version %d.%d)",
321 ust_cmd->reg_msg.pid, ust_cmd->reg_msg.ppid,
322 ust_cmd->reg_msg.uid, ust_cmd->reg_msg.gid,
323 ust_cmd->sock, ust_cmd->reg_msg.name,
324 ust_cmd->reg_msg.major, ust_cmd->reg_msg.minor);
325
326 /*
327 * Lock free enqueue the registration request. The red pill
328 * has been taken! This apps will be part of the *system*.
329 */
330 cds_wfcq_enqueue(&thread_state->ust_cmd_queue->head,
331 &thread_state->ust_cmd_queue->tail,
332 &ust_cmd->node);
333
334 /*
335 * Wake the registration queue futex. Implicit memory
336 * barrier with the exchange in cds_wfcq_enqueue.
337 */
338 futex_nto1_wake(&thread_state->ust_cmd_queue->futex);
339 } else if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
340 ERR("Register apps socket poll error");
341 goto error;
342 } else {
343 ERR("Unexpected poll events %u for sock %d", revents, pollfd);
344 goto error;
345 }
346 }
347 }
348 }
349
350exit:
351error:
352 /* Notify that the registration thread is gone */
353 notify_ust_apps(0, is_root);
354
355 ret = close(application_socket);
356 if (ret) {
357 PERROR("Failed to close application registration socket");
358 }
359 if (sock >= 0) {
360 ret = close(sock);
361 if (ret) {
362 PERROR("Failed to close application socket");
363 }
364 lttng_fd_put(LTTNG_FD_APPS, 1);
365 }
366 unlink(config.apps_unix_sock_path.value);
367
368error_poll_add:
369 lttng_poll_clean(&events);
370error_listen:
371error_create_poll:
372 DBG("UST Registration thread cleanup complete");
373 if (err) {
374 health_error();
375 ERR("Health error occurred in %s", __func__);
376 }
377 health_unregister(health_sessiond);
378 return NULL;
379}
380
381static bool shutdown_application_registration_thread(void *data)
382{
383 struct thread_state *thread_state = data;
384 const int write_fd = lttng_pipe_get_writefd(thread_state->quit_pipe);
385
386 return notify_thread_pipe(write_fd) == 1;
387}
388
389struct lttng_thread *launch_application_registration_thread(
390 struct ust_cmd_queue *cmd_queue)
391{
392 int ret;
393 struct lttng_pipe *quit_pipe;
394 struct thread_state *thread_state = NULL;
395 struct lttng_thread *thread = NULL;
396 const bool is_root = (getuid() == 0);
397 int application_socket = -1;
398
399 thread_state = zmalloc(sizeof(*thread_state));
400 if (!thread_state) {
401 goto error_alloc;
402 }
403 quit_pipe = lttng_pipe_open(FD_CLOEXEC);
404 if (!quit_pipe) {
405 goto error;
406 }
407 thread_state->quit_pipe = quit_pipe;
408 thread_state->ust_cmd_queue = cmd_queue;
409 application_socket = create_application_socket();
410 if (application_socket < 0) {
411 goto error;
412 }
413 thread_state->application_socket = application_socket;
414 sem_init(&thread_state->ready, 0, 0);
415
416 thread = lttng_thread_create("UST application registration",
417 thread_application_registration,
418 shutdown_application_registration_thread,
419 cleanup_application_registration_thread,
420 thread_state);
421 if (!thread) {
422 goto error;
423 }
424 /*
425 * The application registration thread now owns the application socket
426 * and the global thread state. The thread state is used to wait for
427 * the thread's status, but its ownership now belongs to the thread.
428 */
429 application_socket = -1;
430 if (!wait_thread_status(thread_state)) {
431 thread_state = NULL;
432 goto error;
433 }
434
435 /* Notify all applications to register. */
436 ret = notify_ust_apps(1, is_root);
437 if (ret < 0) {
438 ERR("Failed to notify applications or create the wait shared memory.\n"
439 "Execution continues but there might be problems for already\n"
440 "running applications that wishes to register.");
441 }
442
443 return thread;
444error:
445 lttng_thread_put(thread);
446 cleanup_application_registration_thread(thread_state);
447 if (application_socket >= 0) {
448 if (close(application_socket)) {
449 PERROR("Failed to close application registration socket");
450 }
451 }
452error_alloc:
453 return NULL;
454}
This page took 0.024951 seconds and 4 git commands to generate.