Cleanup: apply `include-what-you-use` guideline for `uint*_t`
[lttng-ust.git] / tests / ust-multi-test / ust-multi-test.c
1 /*
2 * ust-multi-test.c - single-proces, multi-session, multi-channel, multi-event UST tracing
3 *
4 * Copyright (C) 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License only.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #define _LARGEFILE64_SOURCE
22 #define _GNU_SOURCE
23 #include <assert.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <limits.h>
27 #include <signal.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/mman.h>
33 #include <sys/resource.h>
34 #include <sys/socket.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <sys/wait.h>
39 #include <unistd.h>
40 #include <urcu/futex.h>
41 #include <urcu/uatomic.h>
42
43 #include <ust-comm.h>
44 #include <lttng/ust-error.h>
45 #include <../../libringbuffer/backend.h>
46 #include <../../libringbuffer/frontend.h>
47 #include "../../liblttng-ust/compat.h" /* For ENODATA */
48
49 #define NR_SESSIONS 4
50 #define NR_CHANNELS 1
51 #define MAX_NR_STREAMS 64
52 #define NR_EVENTS 3
53
54 const char *evname[] = {
55 "ust_tests_hello_tptest",
56 "ust_tests_hello_tptest_sighandler",
57 "ust_tests_hello_dontexist",
58 };
59
60 static int session_handle[NR_SESSIONS];
61 static struct lttng_ust_object_data metadata_stream_data[NR_SESSIONS];
62 static struct lttng_ust_object_data metadata_data[NR_SESSIONS];
63 static struct lttng_ust_object_data channel_data[NR_SESSIONS][NR_CHANNELS];
64 static struct lttng_ust_object_data stream_data[NR_SESSIONS][NR_CHANNELS][MAX_NR_STREAMS];
65 static int event_handle[NR_SESSIONS][NR_CHANNELS][NR_EVENTS];
66
67 static int apps_socket = -1;
68 static char apps_sock_path[PATH_MAX];
69 static char local_apps_wait_shm_path[PATH_MAX];
70
71 static volatile int quit_program;
72
73 static void handle_signals(int signo)
74 {
75 quit_program = 1;
76 }
77
78 static
79 int open_streams(int sock, int channel_handle, struct lttng_ust_object_data *stream_datas,
80 int nr_check)
81 {
82 int ret, k = 0;
83
84 for (;;) {
85 struct ustcomm_ust_msg lum;
86 struct ustcomm_ust_reply lur;
87
88 memset(&lum, 0, sizeof(lum));
89 lum.handle = channel_handle;
90 lum.cmd = LTTNG_UST_STREAM;
91 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
92 if (!ret) {
93 assert(k < nr_check);
94 stream_datas[k].handle = lur.ret_val;
95 printf("received stream handle %u\n",
96 stream_datas[k].handle);
97 if (lur.ret_code == LTTNG_UST_OK) {
98 ssize_t len;
99
100 stream_datas[k].memory_map_size = lur.u.stream.memory_map_size;
101 /* get shm fd */
102 len = ustcomm_recv_fd(sock);
103 if (len < 0)
104 return -EINVAL;
105 stream_datas[k].shm_fd = len;
106 /* get wait fd */
107 len = ustcomm_recv_fd(sock);
108 if (len < 0)
109 return -EINVAL;
110 stream_datas[k].wait_fd = len;
111 }
112 k++;
113 }
114 if (ret == -LTTNG_UST_ERR_NOENT)
115 break;
116 if (ret)
117 return ret;
118 }
119 return 0;
120 }
121
122 static
123 int close_streams(int sock, struct lttng_ust_object_data *stream_datas, int nr_check)
124 {
125 int ret, k;
126
127 for (k = 0; k < nr_check; k++) {
128 struct ustcomm_ust_msg lum;
129 struct ustcomm_ust_reply lur;
130
131 if (!stream_datas[k].handle)
132 continue;
133 memset(&lum, 0, sizeof(lum));
134 lum.handle = stream_datas[k].handle;
135 lum.cmd = LTTNG_UST_RELEASE;
136 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
137 if (ret) {
138 printf("Error closing stream\n");
139 return ret;
140 }
141 if (stream_datas[k].shm_fd >= 0) {
142 ret = close(stream_datas[k].shm_fd);
143 if (ret) {
144 printf("Error closing stream shm_fd\n");
145 return ret;
146 }
147 }
148 if (stream_datas[k].wait_fd >= 0) {
149 ret = close(stream_datas[k].wait_fd);
150 if (ret) {
151 printf("Error closing stream wait_fd\n");
152 return ret;
153 }
154 }
155 }
156 return 0;
157 }
158
159 static
160 struct lttng_ust_shm_handle *map_channel(struct lttng_ust_object_data *chan_data,
161 struct lttng_ust_object_data *stream_datas, int nr_check)
162 {
163 struct lttng_ust_shm_handle *handle;
164 struct channel *chan;
165 int k, ret;
166
167 /* map metadata channel */
168 handle = channel_handle_create(chan_data->shm_fd,
169 chan_data->wait_fd,
170 chan_data->memory_map_size);
171 if (!handle) {
172 printf("create handle error\n");
173 return NULL;
174 }
175 chan_data->shm_fd = -1;
176 chan_data->wait_fd = -1;
177 chan = shmp(handle, handle->chan);
178
179 for (k = 0; k < nr_check; k++) {
180 struct lttng_ust_object_data *stream_data = &stream_datas[k];
181
182 if (!stream_data->handle)
183 break;
184 /* map stream */
185 ret = channel_handle_add_stream(handle,
186 stream_data->shm_fd,
187 stream_data->wait_fd,
188 stream_data->memory_map_size);
189 if (ret) {
190 printf("add stream error\n");
191 goto error_destroy;
192 }
193 stream_data->shm_fd = -1;
194 stream_data->wait_fd = -1;
195 }
196 return handle;
197
198 error_destroy:
199 channel_destroy(chan, handle, 1);
200 return NULL;
201 }
202
203 static
204 void unmap_channel(struct lttng_ust_shm_handle *handle)
205 {
206 struct channel *chan;
207
208 chan = shmp(handle, handle->chan);
209 /* unmap channel */
210 channel_destroy(chan, handle, 1);
211 }
212
213 static
214 int consume_stream(struct lttng_ust_shm_handle *handle, int cpu, char *outfile)
215 {
216 struct channel *chan;
217 struct lttng_ust_lib_ring_buffer *buf;
218 int outfd, ret;
219 int *shm_fd, *wait_fd;
220 uint64_t *memory_map_size;
221
222 chan = shmp(handle, handle->chan);
223
224 /* open stream */
225 buf = channel_get_ring_buffer(&chan->backend.config,
226 chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
227 if (!buf)
228 return -ENOENT;
229 ret = lib_ring_buffer_open_read(buf, handle, 1);
230 if (ret) {
231 return -1;
232 }
233
234 /* copy */
235 outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC,
236 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
237 if (outfd < 0) {
238 perror("open output");
239 return -1;
240 }
241
242 printf("Waiting for buffer data for %s\n", outfile);
243 for (;;) {
244 unsigned long read_size;
245 unsigned long copy_size;
246 char *ptr;
247
248 ret = lib_ring_buffer_get_next_subbuf(buf, handle);
249 printf("get next ret %d\n", ret);
250 if (ret == -ENODATA)
251 break;
252 if (ret == -EAGAIN) {
253 sleep(1);
254 continue;
255 }
256 if (ret) {
257 printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret);
258 return -1;
259 }
260 read_size = lib_ring_buffer_get_read_data_size(
261 &chan->backend.config, buf, handle);
262 read_size = PAGE_ALIGN(read_size);
263 ptr = lib_ring_buffer_read_offset_address(
264 &buf->backend, 0, handle);
265 printf("WRITE: copy %lu bytes\n", read_size);
266 copy_size = write(outfd, ptr, read_size);
267 if (copy_size < read_size) {
268 printf("write issue: copied %lu, expected %lu\n", copy_size, read_size);
269 }
270 lib_ring_buffer_put_next_subbuf(buf, handle);
271 }
272
273 ret = close(outfd);
274 if (ret) {
275 perror("close");
276 return -1;
277 }
278
279 /* close stream */
280 lib_ring_buffer_release_read(buf, handle, 1);
281 return 0;
282 }
283
284 static
285 int consume_buffers(void)
286 {
287 int i, j, k, ret;
288 mode_t old_umask;
289
290 for (i = 0; i < NR_SESSIONS; i++) {
291 char pathname[PATH_MAX];
292 struct lttng_ust_shm_handle *handle;
293
294 snprintf(pathname, PATH_MAX - 1, "/tmp/testtrace%u", i);
295 old_umask = umask(0);
296 ret = mkdir(pathname, S_IRWXU | S_IRWXG);
297 if (ret && errno != EEXIST) {
298 perror("mkdir");
299 umask(old_umask);
300 return -1;
301 }
302 umask(old_umask);
303
304 /* copy metadata */
305 handle = map_channel(&metadata_data[i],
306 &metadata_stream_data[i], 1);
307 if (!handle)
308 return -1;
309 snprintf(pathname, PATH_MAX - 1,
310 "/tmp/testtrace%u/metadata", i);
311 ret = consume_stream(handle, -1, pathname);
312 if (ret && ret != -ENOENT) {
313 printf("Error in consume_stream\n");
314 return ret;
315 }
316 unmap_channel(handle);
317
318 /* copy binary data */
319 for (j = 0; j < NR_CHANNELS; j++) {
320 handle = map_channel(&channel_data[i][j],
321 stream_data[i][j], MAX_NR_STREAMS);
322 if (!handle)
323 return -1;
324 for (k = 0; k < MAX_NR_STREAMS; k++) {
325 snprintf(pathname, PATH_MAX - 1,
326 "/tmp/testtrace%u/data_%u", i, k);
327 ret = consume_stream(handle, k, pathname);
328 if (ret && ret != -ENOENT) {
329 printf("Error in consume_stream\n");
330 return ret;
331 }
332 }
333 unmap_channel(handle);
334 }
335 }
336
337 return 0;
338 }
339
340 int send_app_msgs(int sock)
341 {
342 struct ustcomm_ust_msg lum;
343 struct ustcomm_ust_reply lur;
344 int ret, i, j, k;
345
346 for (i = 0; i < NR_SESSIONS; i++) {
347 /* Create session */
348 memset(&lum, 0, sizeof(lum));
349 lum.handle = LTTNG_UST_ROOT_HANDLE;
350 lum.cmd = LTTNG_UST_SESSION;
351 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
352 if (ret)
353 return ret;
354 session_handle[i] = lur.ret_val;
355 printf("received session handle %u\n", session_handle[i]);
356
357 /* Create metadata channel */
358 memset(&lum, 0, sizeof(lum));
359 lum.handle = session_handle[i];
360 lum.cmd = LTTNG_UST_METADATA;
361 lum.u.channel.overwrite = 0;
362 lum.u.channel.subbuf_size = 32768;
363 lum.u.channel.num_subbuf = 4;
364 lum.u.channel.switch_timer_interval = 0;
365 lum.u.channel.read_timer_interval = 0;
366 lum.u.channel.output = LTTNG_UST_MMAP;
367 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
368 if (ret)
369 return ret;
370 metadata_data[i].handle = lur.ret_val;
371 printf("received metadata handle %u\n", metadata_data[i].handle);
372 if (lur.ret_code == LTTNG_UST_OK) {
373 ssize_t len;
374
375 metadata_data[i].memory_map_size = lur.u.channel.memory_map_size;
376 /* get shm fd */
377 len = ustcomm_recv_fd(sock);
378 if (len < 0)
379 return -EINVAL;
380 metadata_data[i].shm_fd = len;
381 /* get wait fd */
382 len = ustcomm_recv_fd(sock);
383 if (len < 0)
384 return -EINVAL;
385 metadata_data[i].wait_fd = len;
386 }
387
388 ret = open_streams(sock, metadata_data[i].handle,
389 &metadata_stream_data[i], 1);
390 if (ret) {
391 printf("Error in open_streams\n");
392 return ret;
393 }
394
395 /* Create channels */
396 for (j = 0; j < NR_CHANNELS; j++) {
397 memset(&lum, 0, sizeof(lum));
398 lum.handle = session_handle[i];
399 lum.cmd = LTTNG_UST_CHANNEL;
400 //lum.u.channel.overwrite = 0;
401 lum.u.channel.overwrite = 1;
402 lum.u.channel.subbuf_size = 32768;
403 lum.u.channel.num_subbuf = 8;
404 //lum.u.channel.num_subbuf = 4;
405 //lum.u.channel.num_subbuf = 2;
406 lum.u.channel.switch_timer_interval = 0;
407 lum.u.channel.read_timer_interval = 0;
408 lum.u.channel.output = LTTNG_UST_MMAP;
409 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
410 if (ret)
411 return ret;
412 channel_data[i][j].handle = lur.ret_val;
413 printf("received channel handle %u\n", channel_data[i][j].handle);
414 if (lur.ret_code == LTTNG_UST_OK) {
415 ssize_t len;
416
417 channel_data[i][j].memory_map_size = lur.u.channel.memory_map_size;
418 /* get shm fd */
419 len = ustcomm_recv_fd(sock);
420 if (len < 0)
421 return -EINVAL;
422 channel_data[i][j].shm_fd = len;
423 /* get wait fd */
424 len = ustcomm_recv_fd(sock);
425 if (len < 0)
426 return -EINVAL;
427 channel_data[i][j].wait_fd = len;
428 }
429
430 /* Create events */
431 for (k = 0; k < NR_EVENTS; k++) {
432 memset(&lum, 0, sizeof(lum));
433 lum.handle = channel_data[i][j].handle;
434 lum.cmd = LTTNG_UST_EVENT;
435 strncpy(lum.u.event.name, evname[k],
436 LTTNG_UST_SYM_NAME_LEN);
437 lum.u.event.instrumentation = LTTNG_UST_TRACEPOINT;
438 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
439 if (ret)
440 return ret;
441 event_handle[i][j][k] = lur.ret_val;
442 printf("received event handle %u\n", event_handle[i][j][k]);
443 }
444
445 /* Get references to channel streams */
446 ret = open_streams(sock, channel_data[i][j].handle,
447 stream_data[i][j], MAX_NR_STREAMS);
448 if (ret) {
449 printf("Error in open_streams\n");
450 return ret;
451 }
452 }
453
454 memset(&lum, 0, sizeof(lum));
455 lum.handle = session_handle[i];
456 lum.cmd = LTTNG_UST_SESSION_START;
457 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
458 if (ret)
459 return ret;
460 printf("Session handle %u started.\n", session_handle[i]);
461 }
462
463 /* Tell application registration is done */
464 memset(&lum, 0, sizeof(lum));
465 lum.handle = LTTNG_UST_ROOT_HANDLE;
466 lum.cmd = LTTNG_UST_REGISTER_DONE;
467 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
468 if (ret)
469 return ret;
470 printf("Registration done acknowledged.\n");
471
472 sleep(4);
473
474 ret = consume_buffers();
475 if (ret) {
476 printf("Error in consume_buffers\n");
477 return ret;
478 }
479
480 for (i = 0; i < NR_SESSIONS; i++) {
481 /* Release channels */
482 for (j = 0; j < NR_CHANNELS; j++) {
483 /* Release streams */
484 ret = close_streams(sock, stream_data[i][j],
485 MAX_NR_STREAMS);
486 if (ret)
487 return ret;
488
489 /* Release events */
490 for (k = 0; k < NR_EVENTS; k++) {
491 memset(&lum, 0, sizeof(lum));
492 lum.handle = event_handle[i][j][k];
493 lum.cmd = LTTNG_UST_RELEASE;
494 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
495 if (ret)
496 return ret;
497 }
498 memset(&lum, 0, sizeof(lum));
499 lum.handle = channel_data[i][j].handle;
500 lum.cmd = LTTNG_UST_RELEASE;
501 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
502 if (ret)
503 return ret;
504 if (channel_data[i][j].shm_fd >= 0) {
505 ret = close(channel_data[i][j].shm_fd);
506 if (ret)
507 return ret;
508 }
509 if (channel_data[i][j].wait_fd >= 0) {
510 ret = close(channel_data[i][j].wait_fd);
511 if (ret)
512 return ret;
513 }
514 }
515
516 /* Release metadata channel */
517 ret = close_streams(sock, &metadata_stream_data[i], 1);
518 if (ret)
519 return ret;
520
521 memset(&lum, 0, sizeof(lum));
522 lum.handle = metadata_data[i].handle;
523 lum.cmd = LTTNG_UST_RELEASE;
524 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
525 if (ret)
526 return ret;
527 if (metadata_data[i].shm_fd >= 0) {
528 ret = close(metadata_data[i].shm_fd);
529 if (ret)
530 return ret;
531 }
532 if (metadata_data[i].wait_fd >= 0) {
533 ret = close(metadata_data[i].wait_fd);
534 if (ret)
535 return ret;
536 }
537
538 /* Release session */
539 memset(&lum, 0, sizeof(lum));
540 lum.handle = session_handle[i];
541 lum.cmd = LTTNG_UST_RELEASE;
542 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
543 if (ret)
544 return ret;
545 }
546
547 return 0;
548 }
549
550 /*
551 * Using fork to set umask in the child process (not multi-thread safe). We
552 * deal with the shm_open vs ftruncate race (happening when the sessiond owns
553 * the shm and does not let everybody modify it, to ensure safety against
554 * shm_unlink) by simply letting the mmap fail and retrying after a few
555 * seconds. For global shm, everybody has rw access to it until the sessiond
556 * starts.
557 */
558 static int get_wait_shm(char *shm_path, size_t mmap_size, int global)
559 {
560 int wait_shm_fd, ret;
561 mode_t mode;
562
563 /* Default permissions */
564 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
565
566 /* Change owner of the shm path */
567 if (global) {
568 ret = chown(shm_path, 0, 0);
569 if (ret < 0) {
570 if (errno != ENOENT) {
571 perror("chown wait shm");
572 goto error;
573 }
574 }
575
576 /*
577 * If global session daemon, any application can register so the shm
578 * needs to be set in read-only mode for others.
579 */
580 mode |= S_IROTH;
581 } else {
582 ret = chown(shm_path, getuid(), getgid());
583 if (ret < 0) {
584 if (errno != ENOENT) {
585 perror("chown wait shm");
586 goto error;
587 }
588 }
589 }
590
591 /*
592 * Set permissions to the shm even if we did not create the shm.
593 */
594 ret = chmod(shm_path, mode);
595 if (ret < 0) {
596 if (errno != ENOENT) {
597 perror("chmod wait shm");
598 goto error;
599 }
600 }
601
602 /*
603 * We're alone in a child process, so we can modify the process-wide
604 * umask.
605 */
606 umask(~mode);
607
608 /*
609 * Try creating shm (or get rw access). We don't do an exclusive open,
610 * because we allow other processes to create+ftruncate it concurrently.
611 */
612 wait_shm_fd = shm_open(shm_path, O_RDWR | O_CREAT, mode);
613 if (wait_shm_fd < 0) {
614 perror("shm_open wait shm");
615 goto error;
616 }
617
618 ret = ftruncate(wait_shm_fd, mmap_size);
619 if (ret < 0) {
620 perror("ftruncate wait shm");
621 exit(EXIT_FAILURE);
622 }
623
624 ret = fchmod(wait_shm_fd, mode);
625 if (ret < 0) {
626 perror("fchmod");
627 exit(EXIT_FAILURE);
628 }
629
630 printf("Got the wait shm fd %d\n", wait_shm_fd);
631
632 return wait_shm_fd;
633
634 error:
635 printf("Failing to get the wait shm fd\n");
636
637 return -1;
638 }
639
640 int update_futex(int fd, int active)
641 {
642 long page_size;
643 char *wait_shm_mmap;
644 int ret;
645
646 page_size = sysconf(_SC_PAGE_SIZE);
647 if (page_size <= 0) {
648 if (!page_size) {
649 errno = EINVAL;
650 }
651 perror("Error in sysconf(_SC_PAGE_SIZE)");
652 goto error;
653 }
654 wait_shm_mmap = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
655 MAP_SHARED, fd, 0);
656 if (wait_shm_mmap == MAP_FAILED) {
657 perror("mmap");
658 goto error;
659 }
660
661 if (active) {
662 uatomic_set((int32_t *) wait_shm_mmap, 1);
663 if (futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE,
664 INT_MAX, NULL, NULL, 0) < 0) {
665 perror("futex_async");
666 goto error;
667 }
668 } else {
669 uatomic_set((int32_t *) wait_shm_mmap, 0);
670 }
671 ret = munmap(wait_shm_mmap, page_size);
672 if (ret) {
673 perror("Error unmapping wait shm");
674 goto error;
675 }
676 return 0;
677 error:
678 return -1;
679 }
680
681 /*
682 * Set open files limit to unlimited. This daemon can open a large number of
683 * file descriptors in order to consumer multiple kernel traces.
684 */
685 static void set_ulimit(void)
686 {
687 int ret;
688 struct rlimit lim;
689
690 /*
691 * If not root, we cannot increase our max open files. But our
692 * scope is then limited to processes from a single user.
693 */
694 if (getuid() != 0)
695 return;
696 /* The kernel does not allowed an infinite limit for open files */
697 lim.rlim_cur = 65535;
698 lim.rlim_max = 65535;
699
700 ret = setrlimit(RLIMIT_NOFILE, &lim);
701 if (ret < 0) {
702 perror("failed to set open files limit");
703 }
704 }
705
706 int main(int argc, char **argv)
707 {
708 const char *home_dir;
709 char home_rundir[PATH_MAX];
710 char *cmd = NULL;
711 int ret, wait_shm_fd;
712 struct sigaction act;
713 mode_t old_umask = 0;
714 long page_size;
715
716 set_ulimit();
717
718 /* Ignore sigpipe */
719 memset(&act, 0, sizeof(act));
720 ret = sigemptyset(&act.sa_mask);
721 if (ret == -1) {
722 perror("sigemptyset");
723 return -1;
724 }
725
726 act.sa_handler = SIG_IGN;
727 ret = sigaction(SIGPIPE, &act, NULL);
728 if (ret == -1) {
729 perror("sigaction");
730 return -1;
731 }
732
733 /* Handle SIGTERM */
734 act.sa_handler = handle_signals;
735 ret = sigaction(SIGTERM, &act, NULL);
736 if (ret == -1) {
737 perror("sigaction");
738 return -1;
739 }
740 /* Handle SIGINT */
741 ret = sigaction(SIGINT, &act, NULL);
742 if (ret == -1) {
743 perror("sigaction");
744 return -1;
745 }
746
747 page_size = sysconf(_SC_PAGE_SIZE);
748 if (page_size <= 0) {
749 if (!page_size) {
750 errno = EINVAL;
751 }
752 perror("Error in sysconf(_SC_PAGE_SIZE)");
753 return -1;
754 }
755
756 if (geteuid() == 0) {
757 ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
758 if (ret && errno != EEXIST) {
759 perror("mkdir");
760 return -1;
761 }
762 wait_shm_fd = get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
763 page_size, 1);
764 if (wait_shm_fd < 0) {
765 perror("global wait shm error");
766 return -1;
767 }
768 strcpy(apps_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK);
769 old_umask = umask(0);
770 } else {
771 home_dir = (const char *) getenv("HOME");
772 if (!home_dir) {
773 perror("getenv error");
774 return -ENOENT;
775 }
776
777 snprintf(home_rundir, PATH_MAX,
778 LTTNG_HOME_RUNDIR, home_dir);
779
780 ret = mkdir(home_rundir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
781 if (ret && errno != EEXIST) {
782 perror("mkdir");
783 return -1;
784 }
785
786 snprintf(local_apps_wait_shm_path, PATH_MAX,
787 DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid());
788 wait_shm_fd = get_wait_shm(local_apps_wait_shm_path,
789 page_size, 0);
790 if (wait_shm_fd < 0) {
791 perror("local wait shm error");
792 return -1;
793 }
794 snprintf(apps_sock_path, PATH_MAX,
795 DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
796 }
797
798 ret = ustcomm_create_unix_sock(apps_sock_path);
799 if (ret < 0) {
800 perror("create error");
801 return ret;
802 }
803 apps_socket = ret;
804
805 if (getuid() == 0) {
806 /* File permission MUST be 666 */
807 ret = chmod(apps_sock_path,
808 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
809 if (ret < 0) {
810 printf("Set file permissions failed: %s\n", apps_sock_path);
811 perror("chmod");
812 goto end;
813 }
814 umask(old_umask);
815 }
816 ret = ustcomm_listen_unix_sock(apps_socket);
817 if (ret < 0) {
818 perror("listen error");
819 return ret;
820 }
821
822 /* wake up futexes */
823 ret = update_futex(wait_shm_fd, 1);
824 if (ret) {
825 fprintf(stderr, "Error wakeup futex\n");
826 return -1;
827 }
828
829 for (;;) {
830 int sock;
831 ssize_t len;
832 struct {
833 uint32_t major;
834 uint32_t minor;
835 pid_t pid;
836 pid_t ppid;
837 uid_t uid;
838 gid_t gid;
839 uint32_t bits_per_long;
840 char name[16]; /* Process name */
841 } reg_msg;
842 char bufname[17];
843
844 if (quit_program)
845 break;
846
847 printf("Accepting application registration\n");
848 sock = ustcomm_accept_unix_sock(apps_socket);
849 if (sock < 0) {
850 perror("accept error");
851 goto end;
852 }
853
854 /*
855 * Basic recv here to handle the very simple data
856 * that the libust send to register (reg_msg).
857 */
858 len = ustcomm_recv_unix_sock(sock, &reg_msg, sizeof(reg_msg));
859 if (len < 0 || len != sizeof(reg_msg)) {
860 perror("ustcomm_recv_unix_sock");
861 continue;
862 }
863 memcpy(bufname, reg_msg.name, 16);
864 bufname[16] = '\0';
865 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
866 bufname, reg_msg.pid, reg_msg.ppid, reg_msg.uid,
867 reg_msg.gid, reg_msg.major, reg_msg.minor);
868 ret = send_app_msgs(sock);
869 if (ret) {
870 printf("Error in send_app_msgs.\n");
871 sleep(1);
872 }
873 close(sock);
874 }
875
876 end:
877 printf("quitting.\n");
878 /* Let applications know we are not responding anymore */
879 ret = update_futex(wait_shm_fd, 0);
880 if (ret) {
881 fprintf(stderr, "Error wakeup futex\n");
882 return -1;
883 }
884
885 if (geteuid()) {
886 printf("Removing %s directory\n", home_rundir);
887 ret = asprintf(&cmd, "rm -rf %s", home_rundir);
888 if (ret < 0) {
889 printf("asprintf failed. Something is really wrong!\n");
890 return -1;
891 }
892
893 /* Remove lttng run directory */
894 ret = system(cmd);
895 if (ret < 0) {
896 printf("Unable to clean %s\n", home_rundir);
897 return -1;
898 }
899 }
900
901 return 0;
902 }
This page took 0.047139 seconds and 4 git commands to generate.