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